| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/first_run_search_engine_view.h" | 5 #include "chrome/browser/ui/views/first_run_search_engine_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/time.h" | 13 #include "base/time.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/first_run/first_run.h" | 15 #include "chrome/browser/first_run/first_run.h" |
| 16 #include "chrome/browser/first_run/first_run_dialog.h" | 16 #include "chrome/browser/first_run/first_run_dialog.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/search_engines/search_engine_type.h" | 18 #include "chrome/browser/search_engines/search_engine_type.h" |
| 19 #include "chrome/browser/search_engines/template_url.h" | 19 #include "chrome/browser/search_engines/template_url.h" |
| 20 #include "chrome/browser/search_engines/template_url_service.h" | 20 #include "chrome/browser/search_engines/template_url_service.h" |
| 21 #include "chrome/browser/search_engines/template_url_service_factory.h" | 21 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 22 #include "chrome/browser/themes/theme_service.h" |
| 22 #include "grit/chromium_strings.h" | 23 #include "grit/chromium_strings.h" |
| 23 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
| 24 #include "grit/google_chrome_strings.h" | 25 #include "grit/google_chrome_strings.h" |
| 25 #include "grit/locale_settings.h" | 26 #include "grit/locale_settings.h" |
| 26 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
| 27 #include "ui/base/accessibility/accessible_view_state.h" | 28 #include "ui/base/accessibility/accessible_view_state.h" |
| 28 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 29 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
| 30 #include "ui/gfx/canvas.h" | 31 #include "ui/gfx/canvas.h" |
| 31 #include "ui/gfx/font.h" | 32 #include "ui/gfx/font.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 ResourceBundle::GetSharedInstance().GetBitmapNamed(logo_id); | 97 ResourceBundle::GetSharedInstance().GetBitmapNamed(logo_id); |
| 97 logo_image->SetImage(logo_bmp); | 98 logo_image->SetImage(logo_bmp); |
| 98 if (use_small_logos) | 99 if (use_small_logos) |
| 99 logo_image->SetImageSize(gfx::Size(kSmallLogoWidth, kSmallLogoHeight)); | 100 logo_image->SetImageSize(gfx::Size(kSmallLogoWidth, kSmallLogoHeight)); |
| 100 // Tooltip text provides accessibility for low-vision users. | 101 // Tooltip text provides accessibility for low-vision users. |
| 101 logo_image->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); | 102 logo_image->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); |
| 102 choice_view_ = logo_image; | 103 choice_view_ = logo_image; |
| 103 } else { | 104 } else { |
| 104 // No logo -- we must show a text label. | 105 // No logo -- we must show a text label. |
| 105 views::Label* logo_label = new views::Label(search_engine_->short_name()); | 106 views::Label* logo_label = new views::Label(search_engine_->short_name()); |
| 106 logo_label->SetColor(SK_ColorDKGRAY); | 107 logo_label->SetBackgroundColor(SK_ColorWHITE); |
| 108 logo_label->SetEnabledColor(SK_ColorDKGRAY); |
| 107 logo_label->SetFont(logo_label->font().DeriveFont(3, gfx::Font::BOLD)); | 109 logo_label->SetFont(logo_label->font().DeriveFont(3, gfx::Font::BOLD)); |
| 108 logo_label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); | 110 logo_label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); |
| 109 logo_label->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); | 111 logo_label->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); |
| 110 logo_label->SetMultiLine(true); | 112 logo_label->SetMultiLine(true); |
| 111 logo_label->SizeToFit(kSmallLogoWidth); | 113 logo_label->SizeToFit(kSmallLogoWidth); |
| 112 choice_view_ = logo_label; | 114 choice_view_ = logo_label; |
| 113 } | 115 } |
| 114 | 116 |
| 115 // The accessible name of the button provides accessibility for | 117 // The accessible name of the button provides accessibility for |
| 116 // screenreaders. It uses the browser name rather than the text of the | 118 // screenreaders. It uses the browser name rather than the text of the |
| (...skipping 16 matching lines...) Expand all Loading... |
| 133 } else { | 135 } else { |
| 134 return choice_view_->GetPreferredSize().height(); | 136 return choice_view_->GetPreferredSize().height(); |
| 135 } | 137 } |
| 136 } | 138 } |
| 137 | 139 |
| 138 void SearchEngineChoice::SetChoiceViewBounds(int x, int y, int width, | 140 void SearchEngineChoice::SetChoiceViewBounds(int x, int y, int width, |
| 139 int height) { | 141 int height) { |
| 140 choice_view_->SetBounds(x, y, width, height); | 142 choice_view_->SetBounds(x, y, width, height); |
| 141 } | 143 } |
| 142 | 144 |
| 143 FirstRunSearchEngineView::FirstRunSearchEngineView( | 145 FirstRunSearchEngineView::FirstRunSearchEngineView(Profile* profile, |
| 144 Profile* profile, bool randomize) | 146 bool randomize) |
| 145 : background_image_(NULL), | 147 : background_image_(NULL), |
| 146 profile_(profile), | 148 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), |
| 147 text_direction_is_rtl_(base::i18n::IsRTL()), | 149 text_direction_is_rtl_(base::i18n::IsRTL()), |
| 150 template_url_service_loaded_(false), |
| 151 added_to_view_hierarchy_(false), |
| 148 randomize_(randomize) { | 152 randomize_(randomize) { |
| 149 // Don't show ourselves until all the search engines have loaded from | 153 // Don't show ourselves until all the search engines have loaded from |
| 150 // the profile -- otherwise we have nothing to show. | 154 // the profile -- otherwise we have nothing to show. |
| 151 SetVisible(false); | 155 SetVisible(false); |
| 152 | 156 |
| 153 // Start loading the search engines for the given profile. | 157 // Start loading the search engines for the given profile. |
| 154 search_engines_model_ = TemplateURLServiceFactory::GetForProfile(profile_); | 158 DCHECK(template_url_service_); |
| 155 if (search_engines_model_) { | 159 DCHECK(!template_url_service_->loaded()); |
| 156 DCHECK(!search_engines_model_->loaded()); | 160 template_url_service_->AddObserver(this); |
| 157 search_engines_model_->AddObserver(this); | 161 template_url_service_->Load(); |
| 158 search_engines_model_->Load(); | |
| 159 } else { | |
| 160 NOTREACHED(); | |
| 161 } | |
| 162 SetupControls(); | |
| 163 } | 162 } |
| 164 | 163 |
| 165 FirstRunSearchEngineView::~FirstRunSearchEngineView() { | 164 FirstRunSearchEngineView::~FirstRunSearchEngineView() { |
| 166 search_engines_model_->RemoveObserver(this); | 165 template_url_service_->RemoveObserver(this); |
| 167 } | 166 } |
| 168 | 167 |
| 169 string16 FirstRunSearchEngineView::GetWindowTitle() const { | 168 string16 FirstRunSearchEngineView::GetWindowTitle() const { |
| 170 return l10n_util::GetStringUTF16(IDS_FIRSTRUN_DLG_TITLE); | 169 return l10n_util::GetStringUTF16(IDS_FIRSTRUN_DLG_TITLE); |
| 171 } | 170 } |
| 172 | 171 |
| 173 void FirstRunSearchEngineView::ButtonPressed(views::Button* sender, | 172 void FirstRunSearchEngineView::ButtonPressed(views::Button* sender, |
| 174 const views::Event& event) { | 173 const views::Event& event) { |
| 175 SearchEngineChoice* choice = static_cast<SearchEngineChoice*>(sender); | 174 SearchEngineChoice* choice = static_cast<SearchEngineChoice*>(sender); |
| 176 TemplateURLService* template_url_service = | 175 DCHECK(template_url_service_); |
| 177 TemplateURLServiceFactory::GetForProfile(profile_); | 176 template_url_service_->SetSearchEngineDialogSlot(choice->slot()); |
| 178 DCHECK(template_url_service); | |
| 179 template_url_service->SetSearchEngineDialogSlot(choice->slot()); | |
| 180 const TemplateURL* default_search = choice->GetSearchEngine(); | 177 const TemplateURL* default_search = choice->GetSearchEngine(); |
| 181 if (default_search) | 178 if (default_search) |
| 182 template_url_service->SetDefaultSearchProvider(default_search); | 179 template_url_service_->SetDefaultSearchProvider(default_search); |
| 183 | 180 |
| 184 MessageLoop::current()->Quit(); | 181 MessageLoop::current()->Quit(); |
| 185 } | 182 } |
| 186 | 183 |
| 187 void FirstRunSearchEngineView::OnPaint(gfx::Canvas* canvas) { | 184 void FirstRunSearchEngineView::OnPaint(gfx::Canvas* canvas) { |
| 188 // Fill in behind the background image with the standard gray toolbar color. | 185 // Fill in behind the background image with the standard gray toolbar color. |
| 189 canvas->FillRectInt(SkColorSetRGB(237, 238, 237), 0, 0, width(), | 186 canvas->FillRectInt(GetThemeProvider()->GetColor(ThemeService::COLOR_TOOLBAR), |
| 190 background_image_->height()); | 187 0, 0, width(), background_image_->height()); |
| 191 // The rest of the dialog background should be white. | 188 // The rest of the dialog background should be white. |
| 192 DCHECK(height() > background_image_->height()); | 189 DCHECK(height() > background_image_->height()); |
| 193 canvas->FillRectInt(SK_ColorWHITE, 0, background_image_->height(), width(), | 190 canvas->FillRectInt(SK_ColorWHITE, 0, background_image_->height(), width(), |
| 194 height() - background_image_->height()); | 191 height() - background_image_->height()); |
| 195 } | 192 } |
| 196 | 193 |
| 197 void FirstRunSearchEngineView::OnTemplateURLServiceChanged() { | 194 void FirstRunSearchEngineView::OnTemplateURLServiceChanged() { |
| 198 using views::ImageView; | |
| 199 | |
| 200 // We only watch the search engine model change once, on load. Remove | 195 // We only watch the search engine model change once, on load. Remove |
| 201 // observer so we don't try to redraw if engines change under us. | 196 // observer so we don't try to redraw if engines change under us. |
| 202 search_engines_model_->RemoveObserver(this); | 197 template_url_service_->RemoveObserver(this); |
| 203 | 198 |
| 204 // Add search engines in search_engines_model_ to buttons list. The | 199 template_url_service_loaded_ = true; |
| 205 // first three will always be from prepopulated data. | 200 AddSearchEnginesIfPossible(); |
| 206 std::vector<const TemplateURL*> template_urls = | |
| 207 search_engines_model_->GetTemplateURLs(); | |
| 208 | |
| 209 // If we have fewer than two search engines, end search engine dialog | |
| 210 // immediately, leaving imported default search engine setting intact. | |
| 211 if (template_urls.size() < 2) { | |
| 212 MessageLoop::current()->Quit(); | |
| 213 return; | |
| 214 } | |
| 215 | |
| 216 std::vector<const TemplateURL*>::iterator search_engine_iter; | |
| 217 | |
| 218 // Is user's default search engine included in first three prepopulated | |
| 219 // set? If not, we need to expand the dialog to include a fourth engine. | |
| 220 const TemplateURL* default_search_engine = | |
| 221 search_engines_model_->GetDefaultSearchProvider(); | |
| 222 // If the user's default choice is not in the first three search engines | |
| 223 // in template_urls, store it in |default_choice| and provide it as a | |
| 224 // fourth option. | |
| 225 SearchEngineChoice* default_choice = NULL; | |
| 226 | |
| 227 // First, see if we have 4 logos to show (in which case we use small logos). | |
| 228 // We show 4 logos when the default search engine the user has chosen is | |
| 229 // not one of the first three prepopulated engines. | |
| 230 if (template_urls.size() > 3) { | |
| 231 for (search_engine_iter = template_urls.begin() + 3; | |
| 232 search_engine_iter != template_urls.end(); | |
| 233 ++search_engine_iter) { | |
| 234 if (default_search_engine == *search_engine_iter) { | |
| 235 default_choice = new SearchEngineChoice(this, *search_engine_iter, | |
| 236 true); | |
| 237 } | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 // Now that we know what size the logos should be, create new search engine | |
| 242 // choices for the view. If there are 2 search engines, only show 2 | |
| 243 // choices; for 3 or more, show 3 (unless the default is not one of the | |
| 244 // top 3, in which case show 4). | |
| 245 for (search_engine_iter = template_urls.begin(); | |
| 246 search_engine_iter < template_urls.begin() + | |
| 247 (template_urls.size() < 3 ? 2 : 3); | |
| 248 ++search_engine_iter) { | |
| 249 // Push first three engines into buttons: | |
| 250 SearchEngineChoice* choice = new SearchEngineChoice(this, | |
| 251 *search_engine_iter, default_choice != NULL); | |
| 252 search_engine_choices_.push_back(choice); | |
| 253 AddChildView(choice->GetView()); // The logo or text view. | |
| 254 AddChildView(choice); // The button associated with the choice. | |
| 255 } | |
| 256 // Push the default choice to the fourth position. | |
| 257 if (default_choice) { | |
| 258 search_engine_choices_.push_back(default_choice); | |
| 259 AddChildView(default_choice->GetView()); // The logo or text view. | |
| 260 AddChildView(default_choice); // The button associated with the choice. | |
| 261 } | |
| 262 | |
| 263 // Randomize order of logos if option has been set. | |
| 264 if (randomize_) { | |
| 265 std::random_shuffle(search_engine_choices_.begin(), | |
| 266 search_engine_choices_.end(), | |
| 267 base::RandGenerator); | |
| 268 // Assign to each choice the position in which it is shown on the screen. | |
| 269 std::vector<SearchEngineChoice*>::iterator it; | |
| 270 int slot = 0; | |
| 271 for (it = search_engine_choices_.begin(); | |
| 272 it != search_engine_choices_.end(); | |
| 273 it++) { | |
| 274 (*it)->set_slot(slot++); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 // Now that we know how many logos to show, lay out and become visible. | |
| 279 SetVisible(true); | |
| 280 Layout(); | |
| 281 SchedulePaint(); | |
| 282 | |
| 283 // If the widget has detected that a screenreader is running, change the | |
| 284 // button names from "Choose" to the name of the search engine. This works | |
| 285 // around a bug that JAWS ignores the accessible name of a native button. | |
| 286 if (GetWidget() && GetWidget()->IsAccessibleWidget()) { | |
| 287 std::vector<SearchEngineChoice*>::iterator it; | |
| 288 for (it = search_engine_choices_.begin(); | |
| 289 it != search_engine_choices_.end(); | |
| 290 it++) { | |
| 291 (*it)->SetText((*it)->GetSearchEngine()->short_name()); | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 // This will tell screenreaders that they should read the full text | |
| 296 // of this dialog to the user now (rather than waiting for the user | |
| 297 // to explore it). | |
| 298 GetWidget()->NotifyAccessibilityEvent( | |
| 299 this, ui::AccessibilityTypes::EVENT_ALERT, true); | |
| 300 } | 201 } |
| 301 | 202 |
| 302 gfx::Size FirstRunSearchEngineView::GetPreferredSize() { | 203 gfx::Size FirstRunSearchEngineView::GetPreferredSize() { |
| 303 return views::Widget::GetLocalizedContentsSize( | 204 return views::Widget::GetLocalizedContentsSize( |
| 304 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS, | 205 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS, |
| 305 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES); | 206 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES); |
| 306 } | 207 } |
| 307 | 208 |
| 308 void FirstRunSearchEngineView::SetupControls() { | |
| 309 using views::Background; | |
| 310 using views::ImageView; | |
| 311 using views::Label; | |
| 312 | |
| 313 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 314 background_image_ = new views::ImageView(); | |
| 315 background_image_->SetImage(rb.GetBitmapNamed(IDR_SEARCH_ENGINE_DIALOG_TOP)); | |
| 316 background_image_->EnableCanvasFlippingForRTLUI(true); | |
| 317 if (text_direction_is_rtl_) { | |
| 318 background_image_->SetHorizontalAlignment(ImageView::LEADING); | |
| 319 } else { | |
| 320 background_image_->SetHorizontalAlignment(ImageView::TRAILING); | |
| 321 } | |
| 322 | |
| 323 AddChildView(background_image_); | |
| 324 | |
| 325 int label_width = GetPreferredSize().width() - 2 * views::kPanelHorizMargin; | |
| 326 | |
| 327 // Add title and text asking the user to choose a search engine: | |
| 328 title_label_ = new Label(l10n_util::GetStringUTF16( | |
| 329 IDS_FR_SEARCH_MAIN_LABEL)); | |
| 330 title_label_->SetColor(SK_ColorBLACK); | |
| 331 title_label_->SetFont(title_label_->font().DeriveFont(3, gfx::Font::BOLD)); | |
| 332 title_label_->SetMultiLine(true); | |
| 333 title_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); | |
| 334 title_label_->SizeToFit(label_width); | |
| 335 AddChildView(title_label_); | |
| 336 | |
| 337 text_label_ = new Label(l10n_util::GetStringFUTF16( | |
| 338 IDS_FR_SEARCH_TEXT, | |
| 339 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | |
| 340 text_label_->SetColor(SK_ColorBLACK); | |
| 341 text_label_->SetFont(text_label_->font().DeriveFont(1, gfx::Font::NORMAL)); | |
| 342 text_label_->SetMultiLine(true); | |
| 343 text_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); | |
| 344 text_label_->SizeToFit(label_width); | |
| 345 AddChildView(text_label_); | |
| 346 } | |
| 347 | |
| 348 void FirstRunSearchEngineView::Layout() { | 209 void FirstRunSearchEngineView::Layout() { |
| 349 // Disable the close button. | 210 // Disable the close button. |
| 350 GetWidget()->EnableClose(false); | 211 GetWidget()->EnableClose(false); |
| 351 | 212 |
| 352 gfx::Size pref_size = background_image_->GetPreferredSize(); | 213 gfx::Size pref_size = background_image_->GetPreferredSize(); |
| 353 background_image_->SetBounds(0, 0, GetPreferredSize().width(), | 214 background_image_->SetBounds(0, 0, GetPreferredSize().width(), |
| 354 pref_size.height()); | 215 pref_size.height()); |
| 355 | 216 |
| 356 // General vertical spacing between elements: | 217 // General vertical spacing between elements: |
| 357 const int kVertSpacing = 8; | 218 const int kVertSpacing = 8; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 | 311 |
| 451 if (num_choices > 3) { | 312 if (num_choices > 3) { |
| 452 next_h_space = search_engine_choices_[2]->x() + logo_width + | 313 next_h_space = search_engine_choices_[2]->x() + logo_width + |
| 453 logo_padding; | 314 logo_padding; |
| 454 search_engine_choices_[3]->SetBounds(next_h_space, next_v_space, | 315 search_engine_choices_[3]->SetBounds(next_h_space, next_v_space, |
| 455 button_width, button_height); | 316 button_width, button_height); |
| 456 } | 317 } |
| 457 } // if (search_engine_choices.size() > 0) | 318 } // if (search_engine_choices.size() > 0) |
| 458 } | 319 } |
| 459 | 320 |
| 321 void FirstRunSearchEngineView::ViewHierarchyChanged(bool is_add, |
| 322 View* parent, |
| 323 View* child) { |
| 324 View::ViewHierarchyChanged(is_add, parent, child); |
| 325 |
| 326 if (is_add && (child == this)) { |
| 327 background_image_ = new views::ImageView(); |
| 328 background_image_->SetImage( |
| 329 ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| 330 IDR_SEARCH_ENGINE_DIALOG_TOP)); |
| 331 background_image_->EnableCanvasFlippingForRTLUI(true); |
| 332 background_image_->SetHorizontalAlignment(text_direction_is_rtl_ ? |
| 333 views::ImageView::LEADING : views::ImageView::TRAILING); |
| 334 |
| 335 AddChildView(background_image_); |
| 336 |
| 337 int label_width = GetPreferredSize().width() - 2 * views::kPanelHorizMargin; |
| 338 |
| 339 // Add title and text asking the user to choose a search engine: |
| 340 title_label_ = new views::Label(l10n_util::GetStringUTF16( |
| 341 IDS_FR_SEARCH_MAIN_LABEL)); |
| 342 title_label_->SetBackgroundColor( |
| 343 GetThemeProvider()->GetColor(ThemeService::COLOR_TOOLBAR)); |
| 344 title_label_->SetEnabledColor(SK_ColorBLACK); |
| 345 title_label_->SetFont(title_label_->font().DeriveFont(3, gfx::Font::BOLD)); |
| 346 title_label_->SetMultiLine(true); |
| 347 title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 348 title_label_->SizeToFit(label_width); |
| 349 AddChildView(title_label_); |
| 350 |
| 351 text_label_ = new views::Label(l10n_util::GetStringFUTF16( |
| 352 IDS_FR_SEARCH_TEXT, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); |
| 353 text_label_->SetBackgroundColor(SK_ColorWHITE); |
| 354 text_label_->SetEnabledColor(SK_ColorBLACK); |
| 355 text_label_->SetFont(text_label_->font().DeriveFont(1, gfx::Font::NORMAL)); |
| 356 text_label_->SetMultiLine(true); |
| 357 text_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 358 text_label_->SizeToFit(label_width); |
| 359 AddChildView(text_label_); |
| 360 |
| 361 added_to_view_hierarchy_ = true; |
| 362 AddSearchEnginesIfPossible(); |
| 363 } |
| 364 } |
| 365 |
| 460 void FirstRunSearchEngineView::GetAccessibleState( | 366 void FirstRunSearchEngineView::GetAccessibleState( |
| 461 ui::AccessibleViewState* state) { | 367 ui::AccessibleViewState* state) { |
| 462 state->role = ui::AccessibilityTypes::ROLE_ALERT; | 368 state->role = ui::AccessibilityTypes::ROLE_ALERT; |
| 463 } | 369 } |
| 370 |
| 371 void FirstRunSearchEngineView::AddSearchEnginesIfPossible() { |
| 372 if (!template_url_service_loaded_ || !added_to_view_hierarchy_) |
| 373 return; |
| 374 |
| 375 // Add search engines in template_url_service_ to buttons list. The |
| 376 // first three will always be from prepopulated data. |
| 377 std::vector<const TemplateURL*> template_urls = |
| 378 template_url_service_->GetTemplateURLs(); |
| 379 |
| 380 // If we have fewer than two search engines, end search engine dialog |
| 381 // immediately, leaving imported default search engine setting intact. |
| 382 if (template_urls.size() < 2) { |
| 383 MessageLoop::current()->Quit(); |
| 384 return; |
| 385 } |
| 386 |
| 387 std::vector<const TemplateURL*>::iterator search_engine_iter; |
| 388 |
| 389 // Is user's default search engine included in first three prepopulated |
| 390 // set? If not, we need to expand the dialog to include a fourth engine. |
| 391 const TemplateURL* default_search_engine = |
| 392 template_url_service_->GetDefaultSearchProvider(); |
| 393 // If the user's default choice is not in the first three search engines |
| 394 // in template_urls, store it in |default_choice| and provide it as a |
| 395 // fourth option. |
| 396 SearchEngineChoice* default_choice = NULL; |
| 397 |
| 398 // First, see if we have 4 logos to show (in which case we use small logos). |
| 399 // We show 4 logos when the default search engine the user has chosen is |
| 400 // not one of the first three prepopulated engines. |
| 401 if (template_urls.size() > 3) { |
| 402 for (search_engine_iter = template_urls.begin() + 3; |
| 403 search_engine_iter != template_urls.end(); |
| 404 ++search_engine_iter) { |
| 405 if (default_search_engine == *search_engine_iter) { |
| 406 default_choice = new SearchEngineChoice(this, *search_engine_iter, |
| 407 true); |
| 408 } |
| 409 } |
| 410 } |
| 411 |
| 412 // Now that we know what size the logos should be, create new search engine |
| 413 // choices for the view. If there are 2 search engines, only show 2 |
| 414 // choices; for 3 or more, show 3 (unless the default is not one of the |
| 415 // top 3, in which case show 4). |
| 416 for (search_engine_iter = template_urls.begin(); |
| 417 search_engine_iter < template_urls.begin() + |
| 418 (template_urls.size() < 3 ? 2 : 3); |
| 419 ++search_engine_iter) { |
| 420 // Push first three engines into buttons: |
| 421 SearchEngineChoice* choice = new SearchEngineChoice(this, |
| 422 *search_engine_iter, default_choice != NULL); |
| 423 search_engine_choices_.push_back(choice); |
| 424 AddChildView(choice->GetView()); // The logo or text view. |
| 425 AddChildView(choice); // The button associated with the choice. |
| 426 } |
| 427 // Push the default choice to the fourth position. |
| 428 if (default_choice) { |
| 429 search_engine_choices_.push_back(default_choice); |
| 430 AddChildView(default_choice->GetView()); // The logo or text view. |
| 431 AddChildView(default_choice); // The button associated with the choice. |
| 432 } |
| 433 |
| 434 // Randomize order of logos if option has been set. |
| 435 if (randomize_) { |
| 436 std::random_shuffle(search_engine_choices_.begin(), |
| 437 search_engine_choices_.end(), |
| 438 base::RandGenerator); |
| 439 // Assign to each choice the position in which it is shown on the screen. |
| 440 std::vector<SearchEngineChoice*>::iterator it; |
| 441 int slot = 0; |
| 442 for (it = search_engine_choices_.begin(); |
| 443 it != search_engine_choices_.end(); |
| 444 it++) { |
| 445 (*it)->set_slot(slot++); |
| 446 } |
| 447 } |
| 448 |
| 449 // Now that we know how many logos to show, lay out and become visible. |
| 450 SetVisible(true); |
| 451 Layout(); |
| 452 SchedulePaint(); |
| 453 |
| 454 // If the widget has detected that a screenreader is running, change the |
| 455 // button names from "Choose" to the name of the search engine. This works |
| 456 // around a bug that JAWS ignores the accessible name of a native button. |
| 457 if (GetWidget() && GetWidget()->IsAccessibleWidget()) { |
| 458 std::vector<SearchEngineChoice*>::iterator it; |
| 459 for (it = search_engine_choices_.begin(); |
| 460 it != search_engine_choices_.end(); |
| 461 it++) { |
| 462 (*it)->SetText((*it)->GetSearchEngine()->short_name()); |
| 463 } |
| 464 } |
| 465 |
| 466 // This will tell screenreaders that they should read the full text |
| 467 // of this dialog to the user now (rather than waiting for the user |
| 468 // to explore it). |
| 469 GetWidget()->NotifyAccessibilityEvent( |
| 470 this, ui::AccessibilityTypes::EVENT_ALERT, true); |
| 471 } |
| OLD | NEW |