diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 23:01:07 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 23:01:07 +0000 |
commit | adfe188f467fda2936b1a051dff5280afefc5a13 (patch) | |
tree | 7912d2718ec605eee30c2c924ccd1a1f43752e68 /chrome | |
parent | 1de282c6e1cfbe4fed87babe242262b2d72330ff (diff) | |
download | chromium_src-adfe188f467fda2936b1a051dff5280afefc5a13.zip chromium_src-adfe188f467fda2936b1a051dff5280afefc5a13.tar.gz chromium_src-adfe188f467fda2936b1a051dff5280afefc5a13.tar.bz2 |
Add new search engine dialog for first run process.
BUG= 37564
TEST= start Chrome with --first-run enabled -- you should see a new search engine selection dialog.
Review URL: http://codereview.chromium.org/1586005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44416 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
36 files changed, 1079 insertions, 109 deletions
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index c591457..e25a00b 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd @@ -410,6 +410,23 @@ 17 </message> + <!-- The width and height of the First Run Search Engine Selection dialog box in characters and --> + <!-- lines (See above). --> + <message name="IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS" use_name_for_id="true"> + 128 + </message> + <if expr="pp_ifdef('_google_chrome')"> + <message name="IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES" use_name_for_id="true"> + 20 + </message> + </if> + <!-- With text instead of images, the selection dialog is much smaller. --> + <if expr="not pp_ifdef('_google_chrome')"> + <message name="IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES" use_name_for_id="true"> + 14 + </message> + </if> + <!-- The width and height of the Cookies dialog box in characters and lines --> <!-- (See above). --> <message name="IDS_COOKIES_PROMPT_WIDTH_CHARS" use_name_for_id="true"> @@ -455,7 +472,7 @@ 12 </message> - <!-- The width and height of the First Run Search Information mini --> + <!-- The width and height of the First Run Search Information OEM --> <!-- bubble in characters and lines (See above). --> <message name="IDS_FIRSTRUNOEMBUBBLE_DIALOG_WIDTH_CHARS" use_name_for_id="true"> 37 @@ -464,6 +481,15 @@ 3 </message> + <!-- The width and height of the First Run Omnibox Information minimal --> + <!-- bubble in characters and lines (See above). --> + <message name="IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_WIDTH_CHARS" use_name_for_id="true"> + 62 + </message> + <message name="IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_HEIGHT_LINES" use_name_for_id="true"> + 5 + </message> + <!-- The minimum width of javascript alert popups. --> <message name="IDS_ALERT_DIALOG_WIDTH_CHARS" use_name_for_id="true"> 30 diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index baa714b..dc922a9 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -345,6 +345,18 @@ <include name="IDR_WIZARD_ICON_RTL" file="google_chrome/wizard_icon_rtl.png" type="BINDATA" /> <include name="IDR_PRODUCT_ICON_32" file="google_chrome/google_chrome_icon_32.png" type="BINDATA" /> <include name="IDR_INFOBAR_TRANSLATE" file="google_chrome/infobar_translate.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_GOOGLE" file="google_chrome/search_google.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YAHOO" file="google_chrome/search_yahoo.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_BING" file="google_chrome/search_bing.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_ASK" file="google_chrome/search_ask.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_CENTRUMCZ" file="google_chrome/search_centrumcz.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_GOO" file="google_chrome/search_goo.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_MAILRU" file="google_chrome/search_mailru.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_NETSPRINT" file="google_chrome/search_netsprint.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_SEZNAM" file="google_chrome/search_seznam.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_VIRGILIO" file="google_chrome/search_virgilio.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YAHOOJP" file="google_chrome/search_yahoojp.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YANDEX" file="google_chrome/search_yandex.png" type="BINDATA" /> </if> <if expr="not pp_ifdef('_google_chrome')"> @@ -360,6 +372,18 @@ <include name="IDR_WIZARD_ICON_RTL" file="chromium/wizard_icon_rtl.png" type="BINDATA" /> <include name="IDR_PRODUCT_ICON_32" file="chromium/chromium_icon_32.png" type="BINDATA" /> <include name="IDR_INFOBAR_TRANSLATE" file="chromium/infobar_translate.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_GOOGLE" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YAHOO" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_BING" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_ASK" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_CENTRUMCZ" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_GOO" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_MAILRU" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_NETSPRINT" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_SEZNAM" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_VIRGILIO" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YAHOOJP" file="notused.png" type="BINDATA" /> + <include name="IDR_SEARCH_ENGINE_LOGO_YANDEX" file="notused.png" type="BINDATA" /> </if> <if expr="pp_ifdef('_google_chrome') and (os == 'darwin')"> diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 09eee48..8772248 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -43,6 +43,7 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/find_bar.h" #include "chrome/browser/find_bar_controller.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/google_url_tracker.h" #include "chrome/browser/google_util.h" #include "chrome/browser/host_zoom_map.h" @@ -300,12 +301,19 @@ void Browser::CreateBrowserWindow() { return; if (local_state->FindPreference(prefs::kShouldShowFirstRunBubble) && local_state->GetBoolean(prefs::kShouldShowFirstRunBubble)) { - bool show_OEM_bubble = (local_state-> + FirstRun::BubbleType bubble_type = FirstRun::LARGEBUBBLE; + if (local_state-> FindPreference(prefs::kShouldUseOEMFirstRunBubble) && - local_state->GetBoolean(prefs::kShouldUseOEMFirstRunBubble)); + local_state->GetBoolean(prefs::kShouldUseOEMFirstRunBubble)) { + bubble_type = FirstRun::OEMBUBBLE; + } else if (local_state-> + FindPreference(prefs::kShouldUseMinimalFirstRunBubble) && + local_state->GetBoolean(prefs::kShouldUseMinimalFirstRunBubble)) { + bubble_type = FirstRun::MINIMALBUBBLE; + } // Reset the preference so we don't show the bubble for subsequent windows. local_state->ClearPref(prefs::kShouldShowFirstRunBubble); - window_->GetLocationBar()->ShowFirstRunBubble(show_OEM_bubble); + window_->GetLocationBar()->ShowFirstRunBubble(bubble_type); } } diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index f93908b..17838223 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -1022,6 +1022,7 @@ int BrowserMain(const MainFunctionParams& parameters) { master_prefs.homepage_defined, master_prefs.do_import_items, master_prefs.dont_import_items, + master_prefs.run_search_engine_experiment, &process_singleton)) { // The user cancelled the first run dialog box, we should exit Chrome. return ResultCodes::NORMAL_EXIT; diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h index 029cfe2..c4fdcfd 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.h +++ b/chrome/browser/cocoa/location_bar_view_mac.h @@ -17,6 +17,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" #include "chrome/browser/extensions/image_loading_tracker.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/toolbar_model.h" #include "chrome/common/content_settings_types.h" @@ -46,7 +47,9 @@ class LocationBarViewMac : public AutocompleteEditController, virtual ~LocationBarViewMac(); // Overridden from LocationBar: - virtual void ShowFirstRunBubble(bool use_OEM_bubble) { NOTIMPLEMENTED(); } + virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type) { + NOTIMPLEMENTED(); + } virtual std::wstring GetInputString() const; virtual WindowOpenDisposition GetWindowOpenDisposition() const; virtual PageTransition::Type GetPageTransition() const; diff --git a/chrome/browser/first_run.cc b/chrome/browser/first_run.cc index 7304494..88e31a3 100644 --- a/chrome/browser/first_run.cc +++ b/chrome/browser/first_run.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -114,6 +114,18 @@ bool FirstRun::SetOEMFirstRunBubblePref() { return true; } +bool FirstRun::SetMinimalFirstRunBubblePref() { + PrefService* local_state = g_browser_process->local_state(); + if (!local_state) + return false; + if (!local_state->FindPreference(prefs::kShouldUseMinimalFirstRunBubble)) { + local_state->RegisterBooleanPref(prefs::kShouldUseMinimalFirstRunBubble, + false); + local_state->SetBoolean(prefs::kShouldUseMinimalFirstRunBubble, true); + } + return true; +} + int FirstRun::ImportFromFile(Profile* profile, const CommandLine& cmdline) { std::wstring file_path = cmdline.GetSwitchValue(switches::kImportFromFile); if (file_path.empty()) { diff --git a/chrome/browser/first_run.h b/chrome/browser/first_run.h index 8a9fb7a..ca00c67 100644 --- a/chrome/browser/first_run.h +++ b/chrome/browser/first_run.h @@ -31,12 +31,19 @@ class ProcessSingleton; // install work for this user. After that the sentinel file is created. class FirstRun { public: + // There are three types of possible first run bubbles: + typedef enum { + LARGEBUBBLE = 0, // The normal bubble, with search engine choice + OEMBUBBLE, // Smaller bubble for OEM builds + MINIMALBUBBLE // Minimal bubble shown after search engine dialog + } BubbleType; // See ProcessMasterPreferences for more info about this structure. struct MasterPrefs { int ping_delay; bool homepage_defined; int do_import_items; int dont_import_items; + bool run_search_engine_experiment; std::vector<GURL> new_tabs; std::vector<GURL> bookmarks; }; @@ -96,6 +103,11 @@ class FirstRun { // gets going. Returns false if the pref could not be set. static bool SetOEMFirstRunBubblePref(); + // Sets the kShouldUseMinimalFirstRunBubble local state pref so that the + // browser shows the minimal first run bubble once the main message loop + // gets going. Returns false if the pref could not be set. + static bool SetMinimalFirstRunBubblePref(); + // Sets the kShouldShowWelcomePage local state pref so that the browser // loads the welcome tab once the message loop gets going. Returns false // if the pref could not be set. @@ -219,12 +231,15 @@ class FirstRunImportObserver : public ImportObserver { // preferences and will override default behavior of importer. // |dont_import_items| specifies the items *not* to import, specified in master // preferences and will override default behavior of importer. +// |search_engine_experiment| indicates whether the experimental search engine +// window should be shown. // Returns true if the user clicked "Start", false if the user pressed "Cancel" // or closed the dialog. bool OpenFirstRunDialog(Profile* profile, bool homepage_defined, int import_items, int dont_import_items, + bool search_engine_experiment, ProcessSingleton* process_singleton); #endif // CHROME_BROWSER_FIRST_RUN_H_ diff --git a/chrome/browser/first_run_gtk.cc b/chrome/browser/first_run_gtk.cc index 59f3041..87406c4 100644 --- a/chrome/browser/first_run_gtk.cc +++ b/chrome/browser/first_run_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -22,6 +22,7 @@ bool OpenFirstRunDialog(Profile* profile, bool homepage_defined, int import_items, int dont_import_items, + bool search_engine_experiment, ProcessSingleton* process_singleton) { return FirstRunDialog::Show(profile, process_singleton); } diff --git a/chrome/browser/first_run_mac.mm b/chrome/browser/first_run_mac.mm index 687838e..f13bf0b 100644 --- a/chrome/browser/first_run_mac.mm +++ b/chrome/browser/first_run_mac.mm @@ -51,6 +51,7 @@ bool OpenFirstRunDialog(Profile* profile, bool homepage_defined, int import_items, int dont_import_items, + bool search_engine_experiment, ProcessSingleton* process_singleton) { FirstRunController* controller = new FirstRunController; return controller->DoFirstRun(profile, process_singleton); diff --git a/chrome/browser/first_run_win.cc b/chrome/browser/first_run_win.cc index 932bbc5..086a2c4 100644 --- a/chrome/browser/first_run_win.cc +++ b/chrome/browser/first_run_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -320,6 +320,15 @@ bool FirstRun::ProcessMasterPreferences(const FilePath& user_data_dir, } } + if (installer_util::GetDistroBooleanPreference(prefs.get(), + installer_util::master_preferences::kSearchEngineExperimentPref, + &value) && value) { + // Set the first run dialog to include the search choice window. + out_prefs->run_search_engine_experiment = true; + // Set the first run bubble to minimal. + FirstRun::SetMinimalFirstRunBubblePref(); + } + // Note we are skipping all other master preferences if skip-first-run-ui // is *not* specified. if (!installer_util::GetDistroBooleanPreference(prefs.get(), @@ -468,16 +477,19 @@ bool OpenFirstRunDialog(Profile* profile, bool homepage_defined, int import_items, int dont_import_items, + bool search_engine_experiment, ProcessSingleton* process_singleton) { DCHECK(profile); DCHECK(process_singleton); // We need the FirstRunView to outlive its parent, as we retrieve the accept // state from it after the dialog has been closed. - scoped_ptr<FirstRunView> first_run_view(new FirstRunView(profile, - homepage_defined, - import_items, - dont_import_items)); + scoped_ptr<FirstRunView> first_run_view( + new FirstRunView(profile, + homepage_defined, + import_items, + dont_import_items, + search_engine_experiment)); first_run_view->set_parent_owned(false); views::Window* first_run_ui = views::Window::CreateChromeWindow( NULL, gfx::Rect(), first_run_view.get()); @@ -646,6 +658,11 @@ bool FirstRun::ImportSettings(Profile* profile, int browser_type, import_cmd.AppendSwitch(switches::kChromeFrame); } + if (cmdline.HasSwitch(switches::kCountry)) { + import_cmd.AppendSwitchWithValue(switches::kCountry, + cmdline.GetSwitchValueASCII(switches::kCountry)); + } + // Time to launch the process that is going to do the import. base::ProcessHandle import_process; if (!base::LaunchApp(import_cmd, false, false, &import_process)) diff --git a/chrome/browser/gtk/first_run_bubble.cc b/chrome/browser/gtk/first_run_bubble.cc index e33ef4e..911aed9 100644 --- a/chrome/browser/gtk/first_run_bubble.cc +++ b/chrome/browser/gtk/first_run_bubble.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -47,7 +47,7 @@ string16 GetDefaultSearchEngineName(Profile* profile) { void FirstRunBubble::Show(Profile* profile, GtkWidget* anchor, const gfx::Rect& rect, - bool use_OEM_bubble) { + FirstRun::BubbleType bubble_type) { new FirstRunBubble(profile, anchor, rect); } diff --git a/chrome/browser/gtk/first_run_bubble.h b/chrome/browser/gtk/first_run_bubble.h index efc9924..2c1b095 100644 --- a/chrome/browser/gtk/first_run_bubble.h +++ b/chrome/browser/gtk/first_run_bubble.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -14,6 +14,7 @@ #include <vector> #include "base/basictypes.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/gtk/info_bubble_gtk.h" #include "chrome/browser/profile.h" #include "chrome/common/notification_observer.h" @@ -26,7 +27,7 @@ class FirstRunBubble : public InfoBubbleGtkDelegate, static void Show(Profile* profile, GtkWidget* anchor, const gfx::Rect& rect, - bool use_OEM_bubble); + FirstRun::BubbleType bubble_type); // Implements the InfoBubbleGtkDelegate. We are notified when the bubble // is about to be closed. diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index 343092e..2a5a664 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -559,11 +559,11 @@ std::wstring LocationBarViewGtk::GetTitle() const { return std::wstring(); } -void LocationBarViewGtk::ShowFirstRunBubble(bool use_OEM_bubble) { +void LocationBarViewGtk::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) { // We need the browser window to be shown before we can show the bubble, but // we get called before that's happened. Task* task = first_run_bubble_.NewRunnableMethod( - &LocationBarViewGtk::ShowFirstRunBubbleInternal, use_OEM_bubble); + &LocationBarViewGtk::ShowFirstRunBubbleInternal, bubble_type); MessageLoop::current()->PostTask(FROM_HERE, task); } @@ -870,7 +870,8 @@ void LocationBarViewGtk::SetKeywordHintLabel(const std::wstring& keyword) { trailing.c_str()); } -void LocationBarViewGtk::ShowFirstRunBubbleInternal(bool use_OEM_bubble) { +void LocationBarViewGtk::ShowFirstRunBubbleInternal( + FirstRun::BubbleType bubble_type) { if (!location_entry_.get() || !widget()->window) return; @@ -886,7 +887,7 @@ void LocationBarViewGtk::ShowFirstRunBubbleInternal(bool use_OEM_bubble) { x_offset = anchor->allocation.width - kFirstRunBubbleLeftMargin; gfx::Rect rect(x_offset, y_offset, 0, 0); - FirstRunBubble::Show(profile_, anchor, rect, use_OEM_bubble); + FirstRunBubble::Show(profile_, anchor, rect, bubble_type); } gboolean LocationBarViewGtk::OnIconReleased(GtkWidget* sender, diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index 15f76f2..cf7b02f 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -18,6 +18,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" #include "chrome/browser/extensions/extension_context_menu_model.h" #include "chrome/browser/extensions/image_loading_tracker.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/gtk/info_bubble_gtk.h" #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/location_bar.h" @@ -95,7 +96,7 @@ class LocationBarViewGtk : public AutocompleteEditController, virtual std::wstring GetTitle() const; // Implement the LocationBar interface. - virtual void ShowFirstRunBubble(bool use_OEM_bubble); + virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type); virtual std::wstring GetInputString() const; virtual WindowOpenDisposition GetWindowOpenDisposition() const; virtual PageTransition::Type GetPageTransition() const; @@ -291,7 +292,7 @@ class LocationBarViewGtk : public AutocompleteEditController, // Set the keyword text for the "Press tab to search BLAH" hint box. void SetKeywordHintLabel(const std::wstring& keyword); - void ShowFirstRunBubbleInternal(bool use_OEM_bubble); + void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type); // Show or hide |tab_to_search_box_|, |tab_to_search_hint_| and // |type_to_search_hint_| according to the value of |show_selected_keyword_|, diff --git a/chrome/browser/location_bar.h b/chrome/browser/location_bar.h index a0afe93..a30dcf0 100644 --- a/chrome/browser/location_bar.h +++ b/chrome/browser/location_bar.h @@ -13,6 +13,7 @@ #include <string> +#include "chrome/browser/first_run.h" #include "chrome/common/page_transition_types.h" #include "webkit/glue/window_open_disposition.h" @@ -24,7 +25,7 @@ class TabContents; class LocationBar { public: // Shows the first run information bubble anchored to the location bar. - virtual void ShowFirstRunBubble(bool use_OEM_bubble) = 0; + virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type) = 0; // Returns the string of text entered in the location bar. virtual std::wstring GetInputString() const = 0; diff --git a/chrome/browser/views/first_run_bubble.cc b/chrome/browser/views/first_run_bubble.cc index b4f73b1..692650c 100644 --- a/chrome/browser/views/first_run_bubble.cc +++ b/chrome/browser/views/first_run_bubble.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -12,6 +12,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/options_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_model.h" @@ -81,7 +82,7 @@ class FirstRunBubbleView : public FirstRunBubbleViewBase { FirstRunBubbleView(FirstRunBubble* bubble_window, Profile* profile); private: - virtual ~FirstRunBubbleView() { } + virtual ~FirstRunBubbleView() {} // FirstRunBubbleViewBase: void BubbleShown(); @@ -377,19 +378,118 @@ void FirstRunOEMBubbleView::FocusWillChange(View* focused_before, // No buttons in oem_bubble to register focus changes. } +// FirstRunMinimalBubbleView -------------------------------------------------- +// TODO(mirandac): combine FRBubbles more elegantly. http://crbug.com/41353 + +class FirstRunMinimalBubbleView : public FirstRunBubbleViewBase { + public: + explicit FirstRunMinimalBubbleView(FirstRunBubble* bubble_window); + + private: + virtual ~FirstRunMinimalBubbleView() { } + + // FirstRunBubbleViewBase: + void BubbleShown(); + + // Overridden from View: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) { } + virtual void Layout(); + virtual gfx::Size GetPreferredSize(); + + // FocusChangeListener: + virtual void FocusWillChange(View* focused_before, View* focused_now); + + FirstRunBubble* bubble_window_; + views::Label* label1_; + views::Label* label2_; + + DISALLOW_COPY_AND_ASSIGN(FirstRunMinimalBubbleView); +}; + +FirstRunMinimalBubbleView::FirstRunMinimalBubbleView( + FirstRunBubble* bubble_window) + : bubble_window_(bubble_window), + label1_(NULL), + label2_(NULL) { + const gfx::Font& font = + ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont); + + label1_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE)); + label1_->SetFont(font.DeriveFont(3, gfx::Font::BOLD)); + label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + AddChildView(label1_); + + gfx::Size ps = GetPreferredSize(); + + label2_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT)); + label2_->SetMultiLine(true); + label2_->SetFont(font); + label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + label2_->SizeToFit(ps.width() - kBubblePadding * 2); + AddChildView(label2_); +} + +void FirstRunMinimalBubbleView::BubbleShown() { + RequestFocus(); +} + +void FirstRunMinimalBubbleView::Layout() { + gfx::Size canvas = GetPreferredSize(); + + // See comments in FirstRunOEMBubbleView::Layout explaining this hack. + label1_->SetMultiLine(false); + gfx::Size pref_size = label1_->GetPreferredSize(); + label1_->SetMultiLine(true); + label1_->SizeToFit(canvas.width() - kBubblePadding * 2); + label1_->SetBounds(kBubblePadding, kBubblePadding, + canvas.width() - kBubblePadding * 2, + pref_size.height()); + + int next_v_space = label1_->y() + pref_size.height() + + kRelatedControlSmallVerticalSpacing; + + pref_size = label2_->GetPreferredSize(); + label2_->SetBounds(kBubblePadding, next_v_space, + canvas.width() - kBubblePadding * 2, + pref_size.height()); +} + +gfx::Size FirstRunMinimalBubbleView::GetPreferredSize() { + return gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_WIDTH_CHARS, + IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_HEIGHT_LINES)); +} + +void FirstRunMinimalBubbleView::FocusWillChange(View* focused_before, + View* focused_now) { + // No buttons in minimal bubble to register focus changes. +} + + // FirstRunBubble ------------------------------------------------------------- // static FirstRunBubble* FirstRunBubble::Show(Profile* profile, views::Window* parent, const gfx::Rect& position_relative_to, - bool use_OEM_bubble) { + FirstRun::BubbleType bubble_type) { FirstRunBubble* window = new FirstRunBubble(); FirstRunBubbleViewBase* view = NULL; - if (use_OEM_bubble) - view = new FirstRunOEMBubbleView(window, profile); - else - view = new FirstRunBubbleView(window, profile); + + switch (bubble_type) { + case FirstRun::OEMBUBBLE: + view = new FirstRunOEMBubbleView(window, profile); + break; + case FirstRun::LARGEBUBBLE: + view = new FirstRunBubbleView(window, profile); + break; + case FirstRun::MINIMALBUBBLE: + view = new FirstRunMinimalBubbleView(window); + break; + default: + NOTREACHED(); + } window->set_view(view); window->Init(parent, position_relative_to, view, window); window->GetFocusManager()->AddFocusChangeListener(view); diff --git a/chrome/browser/views/first_run_bubble.h b/chrome/browser/views/first_run_bubble.h index 81f870d..cccce32 100644 --- a/chrome/browser/views/first_run_bubble.h +++ b/chrome/browser/views/first_run_bubble.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/task.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/views/info_bubble.h" class FirstRunBubbleViewBase; @@ -17,7 +18,7 @@ class FirstRunBubble : public InfoBubble, public: static FirstRunBubble* Show(Profile* profile, views::Window* window, const gfx::Rect& position_relative_to, - bool use_OEM_bubble); + FirstRun::BubbleType bubble_type); private: FirstRunBubble(); diff --git a/chrome/browser/views/first_run_customize_view.cc b/chrome/browser/views/first_run_customize_view.cc index 263be85..503d75a 100644 --- a/chrome/browser/views/first_run_customize_view.cc +++ b/chrome/browser/views/first_run_customize_view.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -28,9 +28,10 @@ FirstRunCustomizeView::FirstRunCustomizeView(Profile* profile, bool default_browser_checked, bool homepage_defined, int import_items, - int dont_import_items) + int dont_import_items, + bool search_engine_experiment) : FirstRunViewBase(profile, homepage_defined, import_items, - dont_import_items), + dont_import_items, search_engine_experiment), main_label_(NULL), import_cbox_(NULL), import_from_combo_(NULL), @@ -220,13 +221,15 @@ bool FirstRunCustomizeView::Accept() { if (default_browser_ && default_browser_->checked()) SetDefaultBrowser(); - if (customize_observer_) + // The customize observer is responsible for shutting down the startup + // message loop. + if (customize_observer_) { customize_observer_->CustomizeAccepted(); - - // Exit the message loop we were started with so that startup can continue. - MessageLoop::current()->Quit(); - - FirstRunComplete(); + } else { + // Exit the message loop we were started with so that startup can continue. + MessageLoop::current()->Quit(); + FirstRunComplete(); + } return true; } diff --git a/chrome/browser/views/first_run_customize_view.h b/chrome/browser/views/first_run_customize_view.h index dd9a28c..ecc3a7aa 100644 --- a/chrome/browser/views/first_run_customize_view.h +++ b/chrome/browser/views/first_run_customize_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -42,7 +42,8 @@ class FirstRunCustomizeView : public FirstRunViewBase, bool default_browser_checked, bool homepage_defined, int import_items, - int dont_import_items); + int dont_import_items, + bool search_engine_experiment); virtual ~FirstRunCustomizeView(); // Overridden from views::View. diff --git a/chrome/browser/views/first_run_search_engine_view.cc b/chrome/browser/views/first_run_search_engine_view.cc new file mode 100644 index 0000000..48eed28 --- /dev/null +++ b/chrome/browser/views/first_run_search_engine_view.cc @@ -0,0 +1,450 @@ +// 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_search_engine_view.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/i18n/rtl.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/browser/search_engines/template_url_model.h" +#include "gfx/font.h" +#include "grit/browser_resources.h" +#include "grit/chromium_strings.h" +#include "grit/google_chrome_strings.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" +#include "views/controls/button/button.h" +#include "views/controls/image_view.h" +#include "views/controls/label.h" +#include "views/controls/separator.h" +#include "views/standard_layout.h" +#include "views/view_text_utils.h" +#include "views/window/window.h" + +namespace { + +// These strings mark the embedded link in IDS_FIRSTRUN_SEARCH_SUBTEXT. +const wchar_t* kBeginLink = L"BEGIN_LINK_SE"; +const wchar_t* kEndLink = L"END_LINK_SE"; + +// Represents an id for which we have no logo. +const int kNoLogo = -1; + +// Size to scale logos down to if showing 4 instead of 3 choices. Logo images +// are all originally sized at 180 x 120 pixels, with the logo text baseline +// located 74 pixels beneath the top of the image. +const int kSmallLogoWidth = 120; +const int kSmallLogoHeight = 80; + +// Used to pad text label height so it fits nicely in view. +const int kLabelPadding = 25; + +// Maps the prepopulated id of a search engine to its logo. +struct SearchEngineLogo { + // The unique id for a prepopulated search engine; see PrepopulatedEngine + // struct in template_url_prepopulate_data.cc. + int search_engine_id; + + // The IDR that represents the logo image for a given search engine. + int logo_idr; +}; + +// Mapping of prepopulate_id to logo for each search engine. +SearchEngineLogo kSearchEngineLogos[] = { + { 1, IDR_SEARCH_ENGINE_LOGO_GOOGLE }, + { 2, IDR_SEARCH_ENGINE_LOGO_YAHOO }, + { 3, IDR_SEARCH_ENGINE_LOGO_BING }, +}; + +int GetSearchEngineLogo(const TemplateURL* template_url) { + TemplateURL::IDType id = template_url->prepopulate_id(); + if (id > 0) { + for (size_t i = 0; i < arraysize(kSearchEngineLogos); ++i) { + if (kSearchEngineLogos[i].search_engine_id == id) { + return kSearchEngineLogos[i].logo_idr; + } + } + } + // |id| is either not found, or does not exist. + return kNoLogo; +} + +} // namespace + +SearchEngineChoice::SearchEngineChoice(views::ButtonListener* listener, + const TemplateURL* search_engine, + bool use_small_logos) + : NativeButton(listener, l10n_util::GetString(IDS_FR_SEARCH_CHOOSE)), + is_image_label_(false), + search_engine_(search_engine) { + bool use_images = false; +#if defined(GOOGLE_CHROME_BUILD) + use_images = true; +#endif + int logo_id = GetSearchEngineLogo(search_engine_); + if (use_images && logo_id != kNoLogo) { + is_image_label_ = true; + views::ImageView* logo_image = new views::ImageView(); + SkBitmap* logo_bmp = + ResourceBundle::GetSharedInstance().GetBitmapNamed(logo_id); + logo_image->SetImage(logo_bmp); + if (use_small_logos) + logo_image->SetImageSize(gfx::Size(kSmallLogoWidth, kSmallLogoHeight)); + // Tooltip text provides accessibility. + logo_image->SetTooltipText(search_engine_->short_name()); + choice_view_.reset(logo_image); + } else { + // No logo -- we must show a text label. + views::Label* logo_label = new views::Label(search_engine_->short_name()); + logo_label->SetColor(SK_ColorDKGRAY); + logo_label->SetFont(logo_label->font().DeriveFont(2, gfx::Font::NORMAL)); + logo_label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); + logo_label->SetTooltipText(search_engine_->short_name()); + choice_view_.reset(logo_label); + } +} + +int SearchEngineChoice::GetChoiceViewWidth() { + return choice_view_->GetPreferredSize().width(); +} + +int SearchEngineChoice::GetChoiceViewHeight() { + if (!is_image_label_) { + // Labels need to be padded to look nicer. + return choice_view_->GetPreferredSize().height() + kLabelPadding; + } else { + return choice_view_->GetPreferredSize().height(); + } +} + +void SearchEngineChoice::SetChoiceViewBounds(int x, int y, int width, + int height) { + choice_view_->SetBounds(x, y, width, height); +} + +FirstRunSearchEngineView::FirstRunSearchEngineView( + SearchEngineViewObserver* observer, Profile* profile) + : profile_(profile), + observer_(observer), + text_direction_is_rtl_(base::i18n::IsRTL()) { + DCHECK(observer); + // Don't show ourselves until all the search engines have loaded from + // the profile -- otherwise we have nothing to show. + SetVisible(false); + + // Start loading the search engines for the given profile. + search_engines_model_ = profile_->GetTemplateURLModel(); + if (search_engines_model_) { + DCHECK(!search_engines_model_->loaded()); + search_engines_model_->AddObserver(this); + search_engines_model_->Load(); + } else { + NOTREACHED(); + } + SetupControls(); +} + +FirstRunSearchEngineView::~FirstRunSearchEngineView() { + search_engines_model_->RemoveObserver(this); +} + +void FirstRunSearchEngineView::ButtonPressed(views::Button* sender, + const views::Event& event) { + observer_->SearchEngineChosen( + static_cast<SearchEngineChoice*>(sender)->GetSearchEngine()); +} + +void FirstRunSearchEngineView::OnTemplateURLModelChanged() { + using views::ImageView; + + // We only watch the search engine model change once, on load. Remove + // observer so we don't try to redraw if engines change under us. + search_engines_model_->RemoveObserver(this); + + // Add search engines in search_engines_model_ to buttons list. The + // first three will always be from prepopulated data. + std::vector<const TemplateURL*> template_urls = + search_engines_model_->GetTemplateURLs(); + std::vector<const TemplateURL*>::iterator search_engine_iter; + + // Is user's default search engine included in first three prepopulated + // set? If not, we need to expand the dialog to include a fourth engine. + const TemplateURL* default_search_engine = + search_engines_model_->GetDefaultSearchProvider(); + // If the user's default choice is not in the first three search engines + // in template_urls, store it in |default_choice| and provide it as a + // fourth option. + SearchEngineChoice* default_choice = NULL; + + // First, see if we have 4 logos to show (in which case we use small logos). + // We show 4 logos when the default search engine the user has chosen is + // not one of the first three prepopulated engines. + if (template_urls.size() > 3) { + for (search_engine_iter = template_urls.begin() + 3; + search_engine_iter != template_urls.end(); + ++search_engine_iter) { + if (default_search_engine == *search_engine_iter) { + default_choice = new SearchEngineChoice(this, *search_engine_iter, + true); + } + } + } + + // Now that we know what size the logos should be, create new search engine + // choices for the view: + for (search_engine_iter = template_urls.begin(); + search_engine_iter < template_urls.begin() + 3; + ++search_engine_iter) { + // Push first three engines into buttons: + SearchEngineChoice* choice = new SearchEngineChoice(this, + *search_engine_iter, default_choice != NULL); + search_engine_choices_.push_back(choice); + AddChildView(choice->GetView()); + AddChildView(choice); + } + // Push the default choice to the fourth position. + if (default_choice) { + search_engine_choices_.push_back(default_choice); + AddChildView(default_choice); + AddChildView(default_choice->GetView()); + } + + // Now that we know how many logos to show, lay out and become visible. + SetVisible(true); + Layout(); + SchedulePaint(); +} + +void FirstRunSearchEngineView::OnKeywordEditorClosing(bool default_set) { + // If the search engine has been set in the KeywordEditor, pass NULL + // to the observer to show that we did not choose a search engine in this + // dialog, and to notify that we're done with the selection process. + if (default_set) + observer_->SearchEngineChosen(NULL); + // Else, the user cancelled the KeywordEditor, so continue with this dialog. +} + +gfx::Size FirstRunSearchEngineView::GetPreferredSize() { + return views::Window::GetLocalizedContentsSize( + IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS, + IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES); +} + +void FirstRunSearchEngineView::LinkActivated(views::Link* source, + int event_flags) { + // The KeywordEditor is going to modify search_engines_model_, so + // relinquish our observership so we don't try to redraw. + search_engines_model_->RemoveObserver(this); + // Launch search engine editing window from browser options dialog. + KeywordEditorView::ShowAndObserve(profile_, this); +} + +void FirstRunSearchEngineView::SetupControls() { + using views::Background; + using views::ImageView; + using views::Label; + using views::Link; + using views::NativeButton; + + int label_width = GetPreferredSize().width() - 2 * kPanelHorizMargin; + + set_background(Background::CreateSolidBackground(SK_ColorWHITE)); + + // Add title and text asking the user to choose a search engine: + title_label_ = new Label(l10n_util::GetString( + IDS_FR_SEARCH_MAIN_LABEL)); + title_label_->SetColor(SK_ColorBLACK); + title_label_->SetFont(title_label_->font().DeriveFont(1, gfx::Font::BOLD)); + title_label_->SetMultiLine(true); + title_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); + title_label_->SizeToFit(label_width); + AddChildView(title_label_); + + text_label_ = new Label(l10n_util::GetStringF(IDS_FR_SEARCH_TEXT, + l10n_util::GetString(IDS_PRODUCT_NAME))); + text_label_->SetColor(SK_ColorBLACK); + text_label_->SetMultiLine(true); + text_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); + text_label_->SizeToFit(label_width); + AddChildView(text_label_); + + // The first separator marks the start of the search engine choice panel. + separator_1_ = new views::Separator; + AddChildView(separator_1_); + + // The second separator marks the end of the search engine choice panel. + separator_2_ = new views::Separator; + AddChildView(separator_2_); + + // Parse out the link to the internal search engine options dialog. + std::wstring subtext = l10n_util::GetStringF(IDS_FR_SEARCH_SUBTEXT, + l10n_util::GetString(IDS_PRODUCT_NAME)); + + size_t link_begin = subtext.find(kBeginLink); + DCHECK(link_begin != std::wstring::npos); + size_t link_end = subtext.find(kEndLink); + DCHECK(link_end != std::wstring::npos); + + subtext_label_1_ = new Label(subtext.substr(0, link_begin)); + options_link_ = new views::Link(subtext.substr(link_begin + + wcslen(kBeginLink), link_end - link_begin - wcslen(kBeginLink))); + AddChildView(options_link_); + options_link_->SetController(this); + subtext_label_2_ = new Label(subtext.substr(link_end + wcslen(kEndLink))); + + // This label is never actually shown -- it's just used to place the subtext + // strings correctly in the view. + std::wstring dummy_label = subtext.substr(wcslen(kBeginLink) + + wcslen(kEndLink) + 4); + dummy_subtext_label_ = new Label(dummy_label); + dummy_subtext_label_->SetMultiLine(true); + dummy_subtext_label_->SizeToFit(label_width); +} + +void FirstRunSearchEngineView::Layout() { + // General vertical spacing between elements: + const int kVertSpacing = 8; + // Vertical spacing between the logo + button section and the separators: + const int kUpperLogoMargin = 40; + const int kLowerLogoMargin = 65; + // Percentage of vertical space around logos to use for upper padding. + const double kUpperPaddingPercent = 0.1; + + int num_choices = search_engine_choices_.size(); + + // Title and text above top separator. + int label_width = GetPreferredSize().width() - 2 * kPanelHorizMargin; + int label_height = GetPreferredSize().height() - 2 * kPanelVertMargin; + + title_label_->SetBounds(kPanelHorizMargin, kPanelVertMargin, + label_width, title_label_->GetPreferredSize().height()); + + int next_v_space = title_label_->y() + + title_label_->height() + kVertSpacing; + + text_label_->SetBounds(kPanelHorizMargin, next_v_space, + label_width, + text_label_->GetPreferredSize().height()); + next_v_space = text_label_->y() + + text_label_->height() + kVertSpacing; + + separator_1_->SetBounds(kPanelHorizMargin, next_v_space, label_width, + separator_1_->GetPreferredSize().height()); + + // Set the logos and buttons between the upper and lower separators: + if (num_choices > 0) { + int logo_width = search_engine_choices_[0]->GetChoiceViewWidth(); + int logo_height = search_engine_choices_[0]->GetChoiceViewHeight(); + int button_width = search_engine_choices_[0]->GetPreferredSize().width(); + int button_height = search_engine_choices_[0]->GetPreferredSize().height(); + int lower_section_height = dummy_subtext_label_->height() + kVertSpacing + + separator_2_->GetPreferredSize().height(); + int logo_section_height = logo_height + kVertSpacing + button_height; + int lower_section_start = label_height + kPanelVertMargin - + lower_section_height; + int upper_logo_margin = + static_cast<int>((lower_section_start - separator_1_->y() - + separator_1_->height() - logo_section_height) * + kUpperPaddingPercent); + + next_v_space = separator_1_->y() + separator_1_->height() + + upper_logo_margin; + + // The search engine logos (which all have equal size): + int logo_padding = + (label_width - (num_choices * logo_width)) / (num_choices + 1); + + search_engine_choices_[0]->SetChoiceViewBounds( + kPanelHorizMargin + logo_padding, next_v_space, logo_width, + logo_height); + + int next_h_space = search_engine_choices_[0]->GetView()->x() + + logo_width + logo_padding; + search_engine_choices_[1]->SetChoiceViewBounds( + next_h_space, next_v_space, logo_width, logo_height); + + next_h_space = search_engine_choices_[1]->GetView()->x() + logo_width + + logo_padding; + search_engine_choices_[2]->SetChoiceViewBounds( + next_h_space, next_v_space, logo_width, logo_height); + + if (num_choices > 3) { + next_h_space = search_engine_choices_[2]->GetView()->x() + logo_width + + logo_padding; + search_engine_choices_[3]->SetChoiceViewBounds( + next_h_space, next_v_space, logo_width, logo_height); + } + + next_v_space = search_engine_choices_[0]->GetView()->y() + logo_height + + kVertSpacing; + + // The buttons for search engine selection: + int button_padding = logo_padding + logo_width / 2 - button_width / 2; + + search_engine_choices_[0]->SetBounds(kPanelHorizMargin + button_padding, + next_v_space, button_width, + button_height); + + next_h_space = search_engine_choices_[0]->x() + logo_width + logo_padding; + search_engine_choices_[1]->SetBounds(next_h_space, next_v_space, + button_width, button_height); + next_h_space = search_engine_choices_[1]->x() + logo_width + logo_padding; + search_engine_choices_[2]->SetBounds(next_h_space, next_v_space, + button_width, button_height); + + if (num_choices > 3) { + next_h_space = search_engine_choices_[2]->x() + logo_width + + logo_padding; + search_engine_choices_[3]->SetBounds(next_h_space, next_v_space, + button_width, button_height); + } + + // Lower separator and text beneath it. + next_v_space = lower_section_start; + } // if (search_engine_choices.size() > 0) + + separator_2_->SetBounds(kPanelHorizMargin, next_v_space, label_width, + separator_2_->GetPreferredSize().height()); + + next_v_space = separator_2_->y() + separator_2_->height() + kVertSpacing; + + // This label is used by view_text_utils::DrawTextAndPositionUrl in order + // to figure out mirrored x positions for RTL languages. It only needs to + // provide the correct origin and width; height is not used. + dummy_subtext_label_->SetBounds(kPanelHorizMargin, next_v_space, + label_width, dummy_subtext_label_->height()); +} + +void FirstRunSearchEngineView::Paint(gfx::Canvas* canvas) { + views::View::Paint(canvas); + + gfx::Rect link_rect; + gfx::Size position; + gfx::Font font = + ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); + const gfx::Rect label_bounds = dummy_subtext_label_->bounds(); + + view_text_utils::DrawTextAndPositionUrl(canvas, dummy_subtext_label_, + subtext_label_1_->GetText(), options_link_, &link_rect, &position, + text_direction_is_rtl_, label_bounds, font); + view_text_utils::DrawTextAndPositionUrl(canvas, dummy_subtext_label_, + subtext_label_2_->GetText(), NULL, NULL, &position, + text_direction_is_rtl_, label_bounds, font); + + options_link_->SetBounds(link_rect.x(), link_rect.y(), link_rect.width(), + link_rect.height()); +} + +std::wstring FirstRunSearchEngineView::GetWindowTitle() const { + return l10n_util::GetString(IDS_FIRSTRUN_DLG_TITLE); +} + +void FirstRunSearchEngineView::WindowClosing() { + // User decided not to choose a search engine after all. + observer_->SearchEngineChosen(NULL); +} + diff --git a/chrome/browser/views/first_run_search_engine_view.h b/chrome/browser/views/first_run_search_engine_view.h new file mode 100644 index 0000000..3ceedab --- /dev/null +++ b/chrome/browser/views/first_run_search_engine_view.h @@ -0,0 +1,169 @@ +// 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. + +#ifndef CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_ +#define CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_ + +#include <vector> + +#include "base/scoped_ptr.h" +#include "chrome/browser/views/keyword_editor_view.h" +#include "gfx/size.h" +#include "views/controls/button/native_button.h" +#include "views/controls/link.h" +#include "views/view.h" +#include "views/window/window_delegate.h" + +namespace views { +class ButtonListener; +class Label; +class Separator; +class Window; +} + +class Profile; +class TemplateURL; +class TemplateURLModel; + +// This class holds the logo and TemplateURL for a search engine and serves +// as its button in the search engine selection view. +class SearchEngineChoice : public views::NativeButton { + public: + // |listener| is the FirstRunView that waits for the search engine selection + // to complete; |search_engine| holds the data for the particular search + // engine this button represents; |use_small_logos| is true if we're + // displaying more than three choices. + SearchEngineChoice(views::ButtonListener* listener, + const TemplateURL* search_engine, + bool use_small_logos); + + virtual ~SearchEngineChoice() {} + + // These methods return data about the logo or text view associated + // with this search engine choice. + views::View* GetView() { return choice_view_.get(); } + int GetChoiceViewWidth(); + int GetChoiceViewHeight(); + + // Set the bounds for the search engine choice view; called in the + // Layout method, when we know what the new bounds should be. + void SetChoiceViewBounds(int x, int y, int width, int height); + + // Accessor for the search engine data this button represents. + const TemplateURL* GetSearchEngine() { return search_engine_; } + + private: + // Either an ImageView of a logo, or a Label with text. + scoped_ptr<views::View> choice_view_; + + // True if choice_view_ is holding an ImageView. + bool is_image_label_; + + // Data for the search engine held here. + const TemplateURL* search_engine_; + + DISALLOW_COPY_AND_ASSIGN(SearchEngineChoice); +}; + +// This class displays a large search engine choice dialog view during +// initial first run import. +class FirstRunSearchEngineView + : public views::View, + public views::ButtonListener, + public views::LinkController, + public views::WindowDelegate, + public KeywordEditorViewObserver, + public TemplateURLModelObserver { + public: + // This class receives a callback when the search engine dialog closes. + class SearchEngineViewObserver { + public: + virtual ~SearchEngineViewObserver() {} + // Called when the user has chosen a search engine. If the user closes + // the dialog without providing us with a search engine (because the search + // engine has been chosen using the KeywordEditor dialog link, or because + // the user has cancelled), we pass NULL as the default_search parameter. + virtual void SearchEngineChosen(const TemplateURL* default_search) = 0; + }; + + // |observer| is the FirstRunView that waits for us to pass back a search + // engine choice; |profile| allows us to get the set of imported search + // engines, and display the KeywordEditorView on demand. + FirstRunSearchEngineView(SearchEngineViewObserver* observer, + Profile* profile); + virtual ~FirstRunSearchEngineView(); + + // Overridden from views::View: + virtual gfx::Size GetPreferredSize(); + virtual void Layout(); + virtual void Paint(gfx::Canvas* canvas); + + // Overridden from views::LinkActivated: + virtual void LinkActivated(views::Link* source, int event_flags); + + // Overridden from views::WindowDelegate: + virtual std::wstring GetWindowTitle() const; + virtual void WindowClosing(); + views::View* GetContentsView() { return this; } + bool CanResize() const { return false; } + bool CanMaximize() const { return false; } + bool IsAlwaysOnTop() const { return false; } + bool HasAlwaysOnTopMenu() const { return false; } + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Overridden from TemplateURLModelObserver. When the search engines have + // loaded from the profile, we can populate the logos in the dialog box + // to present to the user. + virtual void OnTemplateURLModelChanged(); + + // Overridden from KeywordEditorViewObserver. If the user chooses to edit + // search engines from the traditional KeywordEditorView (by clicking the + // 'search engine options' link in this view), we must wait for that user + // to finish before completing the import process and launching the browser. + virtual void OnKeywordEditorClosing(bool default_set); + + private: + // Initializes the labels and controls in the view. + void SetupControls(); + + // Owned by the profile_. + TemplateURLModel* search_engines_model_; + + // One for each search engine choice offered, either three or four. + std::vector<SearchEngineChoice*> search_engine_choices_; + + // The profile associated with this import process. + Profile* profile_; + + // Gets called back when one of the choice buttons is pressed. + SearchEngineViewObserver* observer_; + + bool text_direction_is_rtl_; + + // UI elements: + // Text above the first horizontal separator + views::Label* title_label_; + views::Label* text_label_; + + // Horizontal separators + views::Separator* separator_1_; + views::Separator* separator_2_; + + // Text below the second horizontal divider. The order of appearance of + // these three elements is language-dependent. + views::Label* subtext_label_1_; + views::Label* subtext_label_2_; + views::Link* options_link_; + + // Used to figure out positioning of embedded links in RTL languages + // (see view_text_utils::DrawTextAndPositionUrl). + views::Label* dummy_subtext_label_; + + DISALLOW_COPY_AND_ASSIGN(FirstRunSearchEngineView); +}; + +#endif // CHROME_BROWSER_VIEWS_FIRST_RUN_SEARCH_ENGINE_VIEW_H_ + diff --git a/chrome/browser/views/first_run_view.cc b/chrome/browser/views/first_run_view.cc index 2ba4bcd..23eb645 100644 --- a/chrome/browser/views/first_run_view.cc +++ b/chrome/browser/views/first_run_view.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -10,7 +10,11 @@ #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" @@ -35,9 +39,10 @@ std::wstring AddBullet(const std::wstring& text) { } // namespace FirstRunView::FirstRunView(Profile* profile, bool homepage_defined, - int import_items, int dont_import_items) + int import_items, int dont_import_items, + bool search_engine_experiment) : FirstRunViewBase(profile, homepage_defined, import_items, - dont_import_items), + dont_import_items, search_engine_experiment), welcome_label_(NULL), actions_label_(NULL), actions_import_(NULL), @@ -66,31 +71,47 @@ void FirstRunView::SetupControls() { welcome_label_->SizeToFit(0); AddChildView(welcome_label_); - actions_label_ = new Label(l10n_util::GetString(IDS_FIRSTRUN_DLG_DETAIL)); + 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_); - // 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(); + 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_); } - 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_); @@ -119,31 +140,34 @@ void FirstRunView::Layout() { 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, - pref_size.width(), pref_size.height()); + label_width, pref_size.height()); AdjustDialogWidth(actions_label_); next_v_space = actions_label_->y() + actions_label_->height() + kVertSpacing; - label_width = width() - (2 * kPanelHorizMargin); - int label_height = actions_import_->GetHeightForWidth(label_width); - actions_import_->SetBounds(kPanelHorizMargin, next_v_space, label_width, - label_height); + 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_); + 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_); + 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; + next_v_space = actions_shorcuts_->y() + + actions_shorcuts_->height() + + kUnrelatedControlVerticalSpacing; + } pref_size = customize_link_->GetPreferredSize(); customize_link_->SetBounds(kPanelHorizMargin, next_v_space, @@ -161,7 +185,16 @@ void FirstRunView::OpenCustomizeDialog() { default_browser_ && default_browser_->checked(), homepage_defined_, import_items_, - dont_import_items_))->Show(); + 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) { @@ -194,6 +227,14 @@ bool FirstRunView::Accept() { 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()); @@ -207,10 +248,17 @@ bool FirstRunView::Cancel() { } // Notification from the customize dialog that the user accepted. Since all -// the work is done there we got nothing else to do. +// 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. @@ -218,3 +266,15 @@ 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()); +} + diff --git a/chrome/browser/views/first_run_view.h b/chrome/browser/views/first_run_view.h index e5f1d7c..7ada990 100644 --- a/chrome/browser/views/first_run_view.h +++ b/chrome/browser/views/first_run_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -7,6 +7,7 @@ #include "chrome/browser/views/first_run_view_base.h" #include "chrome/browser/views/first_run_customize_view.h" +#include "chrome/browser/views/first_run_search_engine_view.h" #include "views/controls/link.h" #include "views/view.h" #include "views/window/dialog_delegate.h" @@ -18,15 +19,18 @@ class Window; class Profile; class ImporterHost; +class TemplateURL; // FirstRunView implements the dialog that welcomes to user to Chrome after // a fresh install. class FirstRunView : public FirstRunViewBase, public views::LinkController, - public FirstRunCustomizeView::CustomizeViewObserver { + public FirstRunCustomizeView::CustomizeViewObserver, + public FirstRunSearchEngineView::SearchEngineViewObserver { public: explicit FirstRunView(Profile* profile, bool homepage_defined, - int import_items, int dont_import_items); + int import_items, int dont_import_items, + bool search_engine_experiment); virtual ~FirstRunView(); bool accepted() const { return accepted_;} @@ -50,6 +54,9 @@ class FirstRunView : public FirstRunViewBase, virtual void CustomizeAccepted(); virtual void CustomizeCanceled(); + // Overridden from SearchEngineViewObserver: + virtual void SearchEngineChosen(const TemplateURL* default_search); + private: // Initializes the controls on the dialog. void SetupControls(); @@ -57,6 +64,9 @@ class FirstRunView : public FirstRunViewBase, // Creates the dialog that allows the user to customize work items. void OpenCustomizeDialog(); + // Creates the search engine selection dialog. + void OpenSearchEngineDialog(); + views::Label* welcome_label_; views::Label* actions_label_; views::Label* actions_import_; diff --git a/chrome/browser/views/first_run_view_base.cc b/chrome/browser/views/first_run_view_base.cc index c83b20e..995ba3a 100644 --- a/chrome/browser/views/first_run_view_base.cc +++ b/chrome/browser/views/first_run_view_base.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -33,7 +33,8 @@ #include "views/window/window.h" FirstRunViewBase::FirstRunViewBase(Profile* profile, bool homepage_defined, - int import_items, int dont_import_items) + int import_items, int dont_import_items, + bool search_engine_experiment) : preferred_width_(0), background_image_(NULL), separator_1_(NULL), @@ -44,7 +45,8 @@ FirstRunViewBase::FirstRunViewBase(Profile* profile, bool homepage_defined, profile_(profile), homepage_defined_(homepage_defined), import_items_(import_items), - dont_import_items_(dont_import_items) { + dont_import_items_(dont_import_items), + search_engine_experiment_(search_engine_experiment) { DCHECK(profile); SetupControls(); } @@ -200,7 +202,9 @@ bool FirstRunViewBase::HasAlwaysOnTopMenu() const { std::wstring FirstRunViewBase::GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const { if (MessageBoxFlags::DIALOGBUTTON_OK == button) - return l10n_util::GetString(IDS_FIRSTRUN_DLG_OK); + return search_engine_experiment_ ? + l10n_util::GetString(IDS_ACCNAME_NEXT) : + l10n_util::GetString(IDS_FIRSTRUN_DLG_OK); // The other buttons get the default text. return std::wstring(); } diff --git a/chrome/browser/views/first_run_view_base.h b/chrome/browser/views/first_run_view_base.h index cefdd63..31b57b4 100644 --- a/chrome/browser/views/first_run_view_base.h +++ b/chrome/browser/views/first_run_view_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -29,7 +29,8 @@ class FirstRunViewBase : public views::View, public views::DialogDelegate { public: explicit FirstRunViewBase(Profile* profile, bool homepage_defined, - int import_items, int dont_import_items); + int import_items, int dont_import_items, + bool search_engine_experiment); virtual ~FirstRunViewBase(); // Overridden from views::View. @@ -92,6 +93,7 @@ class FirstRunViewBase : public views::View, bool homepage_defined_; int import_items_; int dont_import_items_; + bool search_engine_experiment_; private: // Initializes the controls on the dialog. diff --git a/chrome/browser/views/keyword_editor_view.cc b/chrome/browser/views/keyword_editor_view.cc index 9c0e1fc..4a77c75 100644 --- a/chrome/browser/views/keyword_editor_view.cc +++ b/chrome/browser/views/keyword_editor_view.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -51,7 +51,15 @@ void ShowKeywordEditorView(Profile* profile) { static views::Window* open_window = NULL; // static +// The typical case for showing a KeywordEditorView does not involve an +// observer, so use this function signature generally. void KeywordEditorView::Show(Profile* profile) { + KeywordEditorView::ShowAndObserve(profile, NULL); +} + +// static +void KeywordEditorView::ShowAndObserve(Profile* profile, + KeywordEditorViewObserver* observer) { // If this panel is opened from an Incognito window, closing that window can // leave this with a stale pointer. Use the original profile instead. // See http://crbug.com/23359. @@ -64,7 +72,7 @@ void KeywordEditorView::Show(Profile* profile) { DCHECK(!open_window); // Both of these will be deleted when the dialog closes. - KeywordEditorView* keyword_editor = new KeywordEditorView(profile); + KeywordEditorView* keyword_editor = new KeywordEditorView(profile, observer); // Initialize the UI. By passing in an empty rect KeywordEditorView is // queried for its preferred size. @@ -74,9 +82,12 @@ void KeywordEditorView::Show(Profile* profile) { open_window->Show(); } -KeywordEditorView::KeywordEditorView(Profile* profile) +KeywordEditorView::KeywordEditorView(Profile* profile, + KeywordEditorViewObserver* observer) : profile_(profile), - controller_(new KeywordEditorController(profile)) { + observer_(observer), + controller_(new KeywordEditorController(profile)), + default_chosen_(false) { DCHECK(controller_->url_model()); controller_->url_model()->AddObserver(this); Init(); @@ -125,11 +136,15 @@ int KeywordEditorView::GetDialogButtons() const { } bool KeywordEditorView::Accept() { + if (observer_) + observer_->OnKeywordEditorClosing(default_chosen_); open_window = NULL; return true; } bool KeywordEditorView::Cancel() { + if (observer_) + observer_->OnKeywordEditorClosing(default_chosen_); open_window = NULL; return true; } @@ -288,4 +303,5 @@ void KeywordEditorView::MakeDefaultTemplateURL() { controller_->MakeDefaultTemplateURL(table_view_->FirstSelectedRow()); if (new_index >= 0) table_view_->Select(new_index); + default_chosen_ = true; } diff --git a/chrome/browser/views/keyword_editor_view.h b/chrome/browser/views/keyword_editor_view.h index 69ba388..18369c4 100644 --- a/chrome/browser/views/keyword_editor_view.h +++ b/chrome/browser/views/keyword_editor_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -30,6 +30,14 @@ class SkBitmap; class TemplateURLModel; class TemplateURLTableModel; +class KeywordEditorViewObserver { + public: + // Called when the user has finished setting keyword data. + // |default_chosen| is true if user has selected a default search engine + // through this dialog. + virtual void OnKeywordEditorClosing(bool default_chosen) = 0; +}; + // KeywordEditorView allows the user to edit keywords. class KeywordEditorView : public views::View, @@ -43,7 +51,13 @@ class KeywordEditorView : public views::View, // KeywordEditorView already open, it is closed and a new one is shown. static void Show(Profile* profile); - explicit KeywordEditorView(Profile* profile); + // Shows the KeywordEditorView for the specified profile, and passes in + // an observer to be called back on view close. + static void ShowAndObserve(Profile* profile, + KeywordEditorViewObserver* observer); + + KeywordEditorView(Profile* profile, + KeywordEditorViewObserver* observer); virtual ~KeywordEditorView(); // Overridden from EditSearchEngineControllerDelegate. @@ -88,8 +102,14 @@ class KeywordEditorView : public views::View, // The profile. Profile* profile_; + // Observer gets a callback when the KeywordEditorView closes. + KeywordEditorViewObserver* observer_; + scoped_ptr<KeywordEditorController> controller_; + // True if the user has set a default search engine in this dialog. + bool default_chosen_; + // All the views are added as children, so that we don't need to delete // them directly. views::TableView* table_view_; diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index a966485..d6ca539 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -824,7 +824,8 @@ void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) { } #endif -void LocationBarView::ShowFirstRunBubbleInternal(bool use_OEM_bubble) { +void LocationBarView::ShowFirstRunBubbleInternal( + FirstRun::BubbleType bubble_type) { #if defined(OS_WIN) // First run bubble doesn't make sense for Chrome OS. // If the browser is no longer active, let's not show the info bubble, as this // would make the browser the active window again. @@ -843,7 +844,7 @@ void LocationBarView::ShowFirstRunBubbleInternal(bool use_OEM_bubble) { origin.set_x(width() - origin.x()); views::View::ConvertPointToScreen(this, &origin); FirstRunBubble::Show(profile_, GetWindow(), gfx::Rect(origin, gfx::Size()), - use_OEM_bubble); + bubble_type); #endif } @@ -1527,10 +1528,10 @@ bool LocationBarView::StarView::CloseOnEscape() { //////////////////////////////////////////////////////////////////////////////// // LocationBarView, LocationBar implementation: -void LocationBarView::ShowFirstRunBubble(bool use_OEM_bubble) { +void LocationBarView::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) { // We wait 30 milliseconds to open. It allows less flicker. Task* task = first_run_bubble_.NewRunnableMethod( - &LocationBarView::ShowFirstRunBubbleInternal, use_OEM_bubble); + &LocationBarView::ShowFirstRunBubbleInternal, bubble_type); MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 30); } diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h index 2be8812..331028b 100644 --- a/chrome/browser/views/location_bar_view.h +++ b/chrome/browser/views/location_bar_view.h @@ -13,6 +13,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/extensions/extension_context_menu_model.h" #include "chrome/browser/extensions/image_loading_tracker.h" +#include "chrome/browser/first_run.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/toolbar_model.h" @@ -170,7 +171,7 @@ class LocationBarView : public LocationBar, const gfx::Point& p); // Overridden from LocationBar: - virtual void ShowFirstRunBubble(bool use_OEM_bubble); + virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type); virtual std::wstring GetInputString() const; virtual WindowOpenDisposition GetWindowOpenDisposition() const; virtual PageTransition::Type GetPageTransition() const; @@ -505,7 +506,7 @@ class LocationBarView : public LocationBar, #endif // Helper to show the first run info bubble. - void ShowFirstRunBubbleInternal(bool use_OEM_bubble); + void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type); // Current browser. Not owned by us. Browser* browser_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 92e602e..1689163 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2228,6 +2228,8 @@ 'browser/views/first_run_bubble.h', 'browser/views/first_run_customize_view.cc', 'browser/views/first_run_customize_view.h', + 'browser/views/first_run_search_engine_view.cc', + 'browser/views/first_run_search_engine_view.h', 'browser/views/first_run_view.cc', 'browser/views/first_run_view.h', 'browser/views/first_run_view_base.cc', @@ -2947,6 +2949,8 @@ ['include', '^browser/views/toolbar_view.h'], ['include', '^browser/views/unhandled_keyboard_event_handler.cc'], ['include', '^browser/views/unhandled_keyboard_event_handler.h'], + ['include', '^browser/views/view_text_utils.cc'], + ['include', '^browser/views/view_text_utils.h'], ['include', '^browser/window_sizer.cc'], ['include', '^browser/window_sizer.h'], # Exclude all of browser/gtk, then include the things we want. diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index cbe06b4..e54c822 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -308,8 +308,8 @@ const wchar_t kShowUpdatePromotionInfoBar[] = // true, we draw a custom chrome frame (thicker title bar and blue border). const wchar_t kUseCustomChromeFrame[] = L"browser.custom_chrome_frame"; -// Boolean that indicates whether the infobar explaining that search can be done -// directly from the omnibox should be shown. +// Boolean that indicates whether the infobar explaining that search can be +// done directly from the omnibox should be shown. const wchar_t kShowOmniboxSearchHint[] = L"browser.show_omnibox_search_hint"; // Integer that counts the number of times the promo on the NTP has left to be @@ -617,6 +617,13 @@ const wchar_t kShouldShowFirstRunBubble[] = L"show-first-run-bubble"; // This preference is only registered by the first-run procedure. const wchar_t kShouldUseOEMFirstRunBubble[] = L"show-OEM-first-run-bubble"; +// The mere fact that this pref is registered signals that we should show the +// minimal First Run omnibox information bubble when the first +// browser window appears. +// This preference is only registered by the first-run procedure. +const wchar_t kShouldUseMinimalFirstRunBubble[] = + L"show-minimal-first-run-bubble"; + // Signal that we should show the welcome page when we launch Chrome. const wchar_t kShouldShowWelcomePage[] = L"show-welcome-page"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 83424fb..1da45d1 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -218,6 +218,7 @@ extern const wchar_t kOptionsWindowLastTabIndex[]; extern const wchar_t kContentSettingsWindowLastTabIndex[]; extern const wchar_t kShouldShowFirstRunBubble[]; extern const wchar_t kShouldUseOEMFirstRunBubble[]; +extern const wchar_t kShouldUseMinimalFirstRunBubble[]; extern const wchar_t kShouldShowWelcomePage[]; extern const wchar_t kLastKnownGoogleURL[]; diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc index cae9a6d..77c60d9 100644 --- a/chrome/installer/util/master_preferences_constants.cc +++ b/chrome/installer/util/master_preferences_constants.cc @@ -27,6 +27,7 @@ namespace master_preferences { const wchar_t kMakeChromeDefaultForUser[] = L"make_chrome_default_for_user"; const wchar_t kMsi[] = L"msi"; const wchar_t kRequireEula[] = L"require_eula"; + const wchar_t kSearchEngineExperimentPref[] = L"search_engine_experiment"; const wchar_t kSystemLevel[] = L"system_level"; const wchar_t kVerboseLogging[] = L"verbose_logging"; const wchar_t kExtensionsBlock[] = L"extensions.settings"; diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h index c67d7ab..e08d1e4 100644 --- a/chrome/installer/util/master_preferences_constants.h +++ b/chrome/installer/util/master_preferences_constants.h @@ -61,6 +61,8 @@ extern const wchar_t kSystemLevel[]; extern const wchar_t kVerboseLogging[]; // Name of the block that contains the extensions on the master preferences. extern const wchar_t kExtensionsBlock[]; +// Boolean. Use experimental search engine selection dialog. +extern const wchar_t kSearchEngineExperimentPref[]; } } diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc index ba91cbc..80da133 100644 --- a/chrome/installer/util/master_preferences_unittest.cc +++ b/chrome/installer/util/master_preferences_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. // @@ -52,7 +52,8 @@ TEST_F(MasterPreferencesTest, ParseDistroParams) { " \"alternate_shortcut_text\": true,\n" " \"oem_bubble\": true,\n" " \"chrome_shortcut_icon_index\": 1,\n" - " \"ping_delay\": 40\n" + " \"ping_delay\": 40,\n" + " \"search_engine_experiment\": true\n" " },\n" " \"blah\": {\n" " \"import_history\": false\n" @@ -127,6 +128,9 @@ TEST_F(MasterPreferencesTest, ParseDistroParams) { EXPECT_TRUE(installer_util::GetDistroIntegerPreference(prefs.get(), installer_util::master_preferences::kDistroPingDelay, &ping_delay)); EXPECT_EQ(ping_delay, 40); + EXPECT_TRUE(installer_util::GetDistroBooleanPreference(prefs.get(), + installer_util::master_preferences::kSearchEngineExperimentPref, &value) && + value); } TEST_F(MasterPreferencesTest, ParseMissingDistroParams) { diff --git a/chrome/test/test_location_bar.h b/chrome/test/test_location_bar.h index 131af32..4c19d8d 100644 --- a/chrome/test/test_location_bar.h +++ b/chrome/test/test_location_bar.h @@ -5,6 +5,7 @@ #ifndef CHROME_TEST_TEST_LOCATION_BAR_H_ #define CHROME_TEST_TEST_LOCATION_BAR_H_ +#include "chrome/browser/first_run.h" #include "chrome/browser/location_bar.h" #include "chrome/common/page_transition_types.h" #include "webkit/glue/window_open_disposition.h" @@ -27,7 +28,7 @@ class TestLocationBar : public LocationBar { } // Overridden from LocationBar: - virtual void ShowFirstRunBubble(bool use_OEM_bubble) {} + virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {} virtual std::wstring GetInputString() const { return input_string_; } virtual WindowOpenDisposition GetWindowOpenDisposition() const { return disposition_; |