summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-13 23:01:07 +0000
committermirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-13 23:01:07 +0000
commitadfe188f467fda2936b1a051dff5280afefc5a13 (patch)
tree7912d2718ec605eee30c2c924ccd1a1f43752e68 /chrome
parent1de282c6e1cfbe4fed87babe242262b2d72330ff (diff)
downloadchromium_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')
-rw-r--r--chrome/app/resources/locale_settings.grd28
-rw-r--r--chrome/app/theme/theme_resources.grd24
-rw-r--r--chrome/browser/browser.cc14
-rw-r--r--chrome/browser/browser_main.cc1
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.h5
-rw-r--r--chrome/browser/first_run.cc14
-rw-r--r--chrome/browser/first_run.h15
-rw-r--r--chrome/browser/first_run_gtk.cc3
-rw-r--r--chrome/browser/first_run_mac.mm1
-rw-r--r--chrome/browser/first_run_win.cc27
-rw-r--r--chrome/browser/gtk/first_run_bubble.cc4
-rw-r--r--chrome/browser/gtk/first_run_bubble.h5
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc9
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h5
-rw-r--r--chrome/browser/location_bar.h3
-rw-r--r--chrome/browser/views/first_run_bubble.cc114
-rw-r--r--chrome/browser/views/first_run_bubble.h5
-rw-r--r--chrome/browser/views/first_run_customize_view.cc21
-rw-r--r--chrome/browser/views/first_run_customize_view.h5
-rw-r--r--chrome/browser/views/first_run_search_engine_view.cc450
-rw-r--r--chrome/browser/views/first_run_search_engine_view.h169
-rw-r--r--chrome/browser/views/first_run_view.cc140
-rw-r--r--chrome/browser/views/first_run_view.h16
-rw-r--r--chrome/browser/views/first_run_view_base.cc12
-rw-r--r--chrome/browser/views/first_run_view_base.h6
-rw-r--r--chrome/browser/views/keyword_editor_view.cc24
-rw-r--r--chrome/browser/views/keyword_editor_view.h24
-rw-r--r--chrome/browser/views/location_bar_view.cc9
-rw-r--r--chrome/browser/views/location_bar_view.h5
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/common/pref_names.cc11
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--chrome/installer/util/master_preferences_constants.cc1
-rw-r--r--chrome/installer/util/master_preferences_constants.h2
-rw-r--r--chrome/installer/util/master_preferences_unittest.cc8
-rw-r--r--chrome/test/test_location_bar.h3
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_;