• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
6 
7 #if defined(OS_LINUX)
8 #include <gtk/gtk.h>
9 #endif
10 
11 #include "base/command_line.h"
12 #include "base/stl_util-inl.h"
13 #include "base/utf_string_conversions.h"
14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/alternate_nav_url_fetcher.h"
16 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
17 #include "chrome/browser/defaults.h"
18 #include "chrome/browser/extensions/extension_browser_event_router.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/instant/instant_controller.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/search_engines/template_url.h"
23 #include "chrome/browser/search_engines/template_url_model.h"
24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
25 #include "chrome/browser/ui/view_ids.h"
26 #include "chrome/browser/ui/views/browser_dialogs.h"
27 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
28 #include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
29 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
30 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
31 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
32 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
33 #include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
34 #include "chrome/browser/ui/views/location_bar/star_view.h"
35 #include "chrome/common/chrome_switches.h"
36 #include "chrome/common/pref_names.h"
37 #include "content/browser/renderer_host/render_widget_host_view.h"
38 #include "content/common/notification_service.h"
39 #include "grit/generated_resources.h"
40 #include "grit/theme_resources.h"
41 #include "ui/base/accessibility/accessible_view_state.h"
42 #include "ui/base/dragdrop/drag_drop_types.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h"
45 #include "ui/base/theme_provider.h"
46 #include "ui/gfx/canvas_skia.h"
47 #include "ui/gfx/color_utils.h"
48 #include "ui/gfx/skia_util.h"
49 #include "views/controls/label.h"
50 #include "views/drag_utils.h"
51 
52 #if defined(OS_WIN)
53 #include "chrome/browser/ui/views/first_run_bubble.h"
54 #include "chrome/browser/ui/views/location_bar/suggested_text_view.h"
55 #endif
56 
57 using views::View;
58 
59 namespace {
60 
GetTabContentsFromDelegate(LocationBarView::Delegate * delegate)61 TabContents* GetTabContentsFromDelegate(LocationBarView::Delegate* delegate) {
62   const TabContentsWrapper* wrapper = delegate->GetTabContentsWrapper();
63   return wrapper ? wrapper->tab_contents() : NULL;
64 }
65 
66 }  // namespace
67 
68 // static
69 const int LocationBarView::kNormalHorizontalEdgeThickness = 1;
70 const int LocationBarView::kVerticalEdgeThickness = 2;
71 const int LocationBarView::kItemPadding = 3;
72 const int LocationBarView::kIconInternalPadding = 2;
73 const int LocationBarView::kEdgeItemPadding = kItemPadding;
74 const int LocationBarView::kBubbleHorizontalPadding = 1;
75 const char LocationBarView::kViewClassName[] =
76     "browser/ui/views/location_bar/LocationBarView";
77 
78 static const int kEVBubbleBackgroundImages[] = {
79   IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_L,
80   IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_C,
81   IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_R,
82 };
83 
84 static const int kSelectedKeywordBackgroundImages[] = {
85   IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L,
86   IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C,
87   IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R,
88 };
89 
90 static const int kNormalModeBackgroundImages[] = {
91   IDR_LOCATIONBG_L,
92   IDR_LOCATIONBG_C,
93   IDR_LOCATIONBG_R,
94 };
95 
96 // LocationBarView -----------------------------------------------------------
97 
LocationBarView(Profile * profile,CommandUpdater * command_updater,ToolbarModel * model,Delegate * delegate,Mode mode)98 LocationBarView::LocationBarView(Profile* profile,
99                                  CommandUpdater* command_updater,
100                                  ToolbarModel* model,
101                                  Delegate* delegate,
102                                  Mode mode)
103     : profile_(profile),
104       command_updater_(command_updater),
105       model_(model),
106       delegate_(delegate),
107       disposition_(CURRENT_TAB),
108       transition_(PageTransition::LINK),
109       location_icon_view_(NULL),
110       ev_bubble_view_(NULL),
111       location_entry_view_(NULL),
112       selected_keyword_view_(NULL),
113 #if defined(OS_WIN)
114       suggested_text_view_(NULL),
115 #endif
116       keyword_hint_view_(NULL),
117       star_view_(NULL),
118       mode_(mode),
119       show_focus_rect_(false),
120       bubble_type_(FirstRun::MINIMAL_BUBBLE),
121       template_url_model_(NULL) {
122   DCHECK(profile_);
123   SetID(VIEW_ID_LOCATION_BAR);
124   SetFocusable(true);
125 
126   if (mode_ == NORMAL)
127     painter_.reset(new views::HorizontalPainter(kNormalModeBackgroundImages));
128 
129   edit_bookmarks_enabled_.Init(prefs::kEditBookmarksEnabled,
130                                profile_->GetPrefs(), this);
131 }
132 
~LocationBarView()133 LocationBarView::~LocationBarView() {
134   if (template_url_model_)
135     template_url_model_->RemoveObserver(this);
136 }
137 
Init()138 void LocationBarView::Init() {
139   if (mode_ == POPUP) {
140     font_ = ResourceBundle::GetSharedInstance().GetFont(
141         ResourceBundle::BaseFont);
142   } else {
143     // Use a larger version of the system font.
144     font_ = ResourceBundle::GetSharedInstance().GetFont(
145         ResourceBundle::MediumFont);
146   }
147 
148   // If this makes the font too big, try to make it smaller so it will fit.
149   const int height =
150       std::max(GetPreferredSize().height() - (kVerticalEdgeThickness * 2), 0);
151   while ((font_.GetHeight() > height) && (font_.GetFontSize() > 1))
152     font_ = font_.DeriveFont(-1);
153 
154   location_icon_view_ = new LocationIconView(this);
155   AddChildView(location_icon_view_);
156   location_icon_view_->SetVisible(true);
157   location_icon_view_->SetDragController(this);
158 
159   ev_bubble_view_ =
160       new EVBubbleView(kEVBubbleBackgroundImages, IDR_OMNIBOX_HTTPS_VALID,
161                        GetColor(ToolbarModel::EV_SECURE, SECURITY_TEXT), this);
162   AddChildView(ev_bubble_view_);
163   ev_bubble_view_->SetVisible(false);
164   ev_bubble_view_->SetDragController(this);
165 
166   // URL edit field.
167   // View container for URL edit field.
168 #if defined(OS_WIN)
169   location_entry_.reset(new AutocompleteEditViewWin(font_, this, model_, this,
170       GetWidget()->GetNativeView(), profile_, command_updater_,
171       mode_ == POPUP, this));
172 #else
173   location_entry_.reset(
174       AutocompleteEditViewGtk::Create(
175           this, model_, profile_,
176           command_updater_, mode_ == POPUP, this));
177 #endif
178 
179   location_entry_view_ = location_entry_->AddToView(this);
180   location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE);
181 
182   selected_keyword_view_ = new SelectedKeywordView(
183       kSelectedKeywordBackgroundImages, IDR_KEYWORD_SEARCH_MAGNIFIER,
184       GetColor(ToolbarModel::NONE, TEXT), profile_),
185   AddChildView(selected_keyword_view_);
186   selected_keyword_view_->SetFont(font_);
187   selected_keyword_view_->SetVisible(false);
188 
189   SkColor dimmed_text = GetColor(ToolbarModel::NONE, DEEMPHASIZED_TEXT);
190 
191   keyword_hint_view_ = new KeywordHintView(profile_);
192   AddChildView(keyword_hint_view_);
193   keyword_hint_view_->SetVisible(false);
194   keyword_hint_view_->SetFont(font_);
195   keyword_hint_view_->SetColor(dimmed_text);
196 
197   for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
198     ContentSettingImageView* content_blocked_view = new ContentSettingImageView(
199         static_cast<ContentSettingsType>(i), this, profile_);
200     content_setting_views_.push_back(content_blocked_view);
201     AddChildView(content_blocked_view);
202     content_blocked_view->SetVisible(false);
203   }
204 
205   // The star is not visible in popups and in the app launcher.
206   if (browser_defaults::bookmarks_enabled && (mode_ == NORMAL)) {
207     star_view_ = new StarView(command_updater_);
208     AddChildView(star_view_);
209     star_view_->SetVisible(true);
210   }
211 
212   // Initialize the location entry. We do this to avoid a black flash which is
213   // visible when the location entry has just been initialized.
214   Update(NULL);
215 
216   OnChanged();
217 }
218 
IsInitialized() const219 bool LocationBarView::IsInitialized() const {
220   return location_entry_view_ != NULL;
221 }
222 
223 // static
GetColor(ToolbarModel::SecurityLevel security_level,ColorKind kind)224 SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level,
225                                   ColorKind kind) {
226   switch (kind) {
227 #if defined(OS_WIN)
228     case BACKGROUND:    return color_utils::GetSysSkColor(COLOR_WINDOW);
229     case TEXT:          return color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
230     case SELECTED_TEXT: return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT);
231 #else
232     // TODO(beng): source from theme provider.
233     case BACKGROUND:    return SK_ColorWHITE;
234     case TEXT:          return SK_ColorBLACK;
235     case SELECTED_TEXT: return SK_ColorWHITE;
236 #endif
237 
238     case DEEMPHASIZED_TEXT:
239       return color_utils::AlphaBlend(GetColor(security_level, TEXT),
240                                      GetColor(security_level, BACKGROUND), 128);
241 
242     case SECURITY_TEXT: {
243       SkColor color;
244       switch (security_level) {
245         case ToolbarModel::EV_SECURE:
246         case ToolbarModel::SECURE:
247           color = SkColorSetRGB(7, 149, 0);
248           break;
249 
250         case ToolbarModel::SECURITY_WARNING:
251           return GetColor(security_level, DEEMPHASIZED_TEXT);
252           break;
253 
254         case ToolbarModel::SECURITY_ERROR:
255           color = SkColorSetRGB(162, 0, 0);
256           break;
257 
258         default:
259           NOTREACHED();
260           return GetColor(security_level, TEXT);
261       }
262       return color_utils::GetReadableColor(color, GetColor(security_level,
263                                                            BACKGROUND));
264     }
265 
266     default:
267       NOTREACHED();
268       return GetColor(security_level, TEXT);
269   }
270 }
271 
Update(const TabContents * tab_for_state_restoring)272 void LocationBarView::Update(const TabContents* tab_for_state_restoring) {
273   bool star_enabled = star_view_ && !model_->input_in_progress() &&
274                       edit_bookmarks_enabled_.GetValue();
275   command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE, star_enabled);
276   if (star_view_)
277     star_view_->SetVisible(star_enabled);
278   RefreshContentSettingViews();
279   RefreshPageActionViews();
280   // Don't Update in app launcher mode so that the location entry does not show
281   // a URL or security background.
282   if (mode_ != APP_LAUNCHER)
283     location_entry_->Update(tab_for_state_restoring);
284   OnChanged();
285 }
286 
UpdateContentSettingsIcons()287 void LocationBarView::UpdateContentSettingsIcons() {
288   RefreshContentSettingViews();
289 
290   Layout();
291   SchedulePaint();
292 }
293 
UpdatePageActions()294 void LocationBarView::UpdatePageActions() {
295   size_t count_before = page_action_views_.size();
296   RefreshPageActionViews();
297   if (page_action_views_.size() != count_before) {
298     NotificationService::current()->Notify(
299         NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
300         Source<LocationBar>(this),
301         NotificationService::NoDetails());
302   }
303 
304   Layout();
305   SchedulePaint();
306 }
307 
InvalidatePageActions()308 void LocationBarView::InvalidatePageActions() {
309   size_t count_before = page_action_views_.size();
310   DeletePageActionViews();
311   if (page_action_views_.size() != count_before) {
312     NotificationService::current()->Notify(
313         NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
314         Source<LocationBar>(this),
315         NotificationService::NoDetails());
316   }
317 }
318 
OnFocus()319 void LocationBarView::OnFocus() {
320   // Focus the location entry native view.
321   location_entry_->SetFocus();
322   GetWidget()->NotifyAccessibilityEvent(
323       this, ui::AccessibilityTypes::EVENT_FOCUS, true);
324 }
325 
SetProfile(Profile * profile)326 void LocationBarView::SetProfile(Profile* profile) {
327   DCHECK(profile);
328   if (profile_ != profile) {
329     profile_ = profile;
330     location_entry_->model()->SetProfile(profile);
331     selected_keyword_view_->set_profile(profile);
332     keyword_hint_view_->set_profile(profile);
333     for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
334          i != content_setting_views_.end(); ++i)
335       (*i)->set_profile(profile);
336   }
337 }
338 
SetPreviewEnabledPageAction(ExtensionAction * page_action,bool preview_enabled)339 void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction* page_action,
340                                                   bool preview_enabled) {
341   if (mode_ != NORMAL)
342     return;
343 
344   DCHECK(page_action);
345   TabContents* contents = GetTabContentsFromDelegate(delegate_);
346 
347   RefreshPageActionViews();
348   PageActionWithBadgeView* page_action_view =
349       static_cast<PageActionWithBadgeView*>(GetPageActionView(page_action));
350   DCHECK(page_action_view);
351   if (!page_action_view)
352     return;
353 
354   page_action_view->image_view()->set_preview_enabled(preview_enabled);
355   page_action_view->UpdateVisibility(contents,
356       GURL(WideToUTF8(model_->GetText())));
357   Layout();
358   SchedulePaint();
359 }
360 
GetPageActionView(ExtensionAction * page_action)361 views::View* LocationBarView::GetPageActionView(
362     ExtensionAction *page_action) {
363   DCHECK(page_action);
364   for (PageActionViews::const_iterator i(page_action_views_.begin());
365        i != page_action_views_.end(); ++i) {
366     if ((*i)->image_view()->page_action() == page_action)
367       return *i;
368   }
369   return NULL;
370 }
371 
SetStarToggled(bool on)372 void LocationBarView::SetStarToggled(bool on) {
373   if (star_view_)
374     star_view_->SetToggled(on);
375 }
376 
ShowStarBubble(const GURL & url,bool newly_bookmarked)377 void LocationBarView::ShowStarBubble(const GURL& url, bool newly_bookmarked) {
378   gfx::Rect screen_bounds(star_view_->GetImageBounds());
379   // Compensate for some built-in padding in the Star image.
380   screen_bounds.Inset(1, 1, 1, 2);
381   gfx::Point origin(screen_bounds.origin());
382   views::View::ConvertPointToScreen(star_view_, &origin);
383   screen_bounds.set_origin(origin);
384   browser::ShowBookmarkBubbleView(GetWindow(), screen_bounds, star_view_,
385                                   profile_, url, newly_bookmarked);
386 }
387 
GetLocationEntryOrigin() const388 gfx::Point LocationBarView::GetLocationEntryOrigin() const {
389   gfx::Point origin(location_entry_view_->bounds().origin());
390   // If the UI layout is RTL, the coordinate system is not transformed and
391   // therefore we need to adjust the X coordinate so that bubble appears on the
392   // right hand side of the location bar.
393   if (base::i18n::IsRTL())
394     origin.set_x(width() - origin.x());
395   views::View::ConvertPointToScreen(this, &origin);
396   return origin;
397 }
398 
399 #if defined(OS_WIN)
SetInstantSuggestion(const string16 & text,bool animate_to_complete)400 void LocationBarView::SetInstantSuggestion(const string16& text,
401                                            bool animate_to_complete) {
402   // Don't show the suggested text if inline autocomplete is prevented.
403   if (!text.empty()) {
404     if (!suggested_text_view_) {
405       suggested_text_view_ = new SuggestedTextView(location_entry_->model());
406       suggested_text_view_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
407       suggested_text_view_->SetColor(
408           GetColor(ToolbarModel::NONE,
409                    LocationBarView::DEEMPHASIZED_TEXT));
410       suggested_text_view_->SetText(UTF16ToWide(text));
411       suggested_text_view_->SetFont(location_entry_->GetFont());
412       AddChildView(suggested_text_view_);
413     } else if (suggested_text_view_->GetText() != UTF16ToWide(text)) {
414       suggested_text_view_->SetText(UTF16ToWide(text));
415     }
416     if (animate_to_complete && !location_entry_->IsImeComposing())
417       suggested_text_view_->StartAnimation();
418   } else if (suggested_text_view_) {
419     delete suggested_text_view_;
420     suggested_text_view_ = NULL;
421   } else {
422     return;
423   }
424 
425   Layout();
426   SchedulePaint();
427 }
428 
GetInstantSuggestion() const429 string16 LocationBarView::GetInstantSuggestion() const {
430   return HasValidSuggestText() ? suggested_text_view_->GetText() : string16();
431 }
432 #endif
433 
GetPreferredSize()434 gfx::Size LocationBarView::GetPreferredSize() {
435   return gfx::Size(0, GetThemeProvider()->GetBitmapNamed(mode_ == POPUP ?
436       IDR_LOCATIONBG_POPUPMODE_CENTER : IDR_LOCATIONBG_C)->height());
437 }
438 
Layout()439 void LocationBarView::Layout() {
440   if (!location_entry_.get())
441     return;
442 
443   // TODO(sky): baseline layout.
444   int location_y = kVerticalEdgeThickness;
445   // In some cases (e.g. fullscreen mode) we may have 0 height.  We still want
446   // to position our child views in this case, because other things may be
447   // positioned relative to them (e.g. the "bookmark added" bubble if the user
448   // hits ctrl-d).
449   int location_height = std::max(height() - (kVerticalEdgeThickness * 2), 0);
450 
451   // The edge stroke is 1 px thick.  In popup mode, the edges are drawn by the
452   // omnibox' parent, so there isn't any edge to account for at all.
453   const int kEdgeThickness = (mode_ == NORMAL) ?
454       kNormalHorizontalEdgeThickness : 0;
455   // The edit has 1 px of horizontal whitespace inside it before the text.
456   const int kEditInternalSpace = 1;
457   // The space between an item and the edit is the normal item space, minus the
458   // edit's built-in space (so the apparent space will be the same).
459   const int kItemEditPadding =
460       LocationBarView::kItemPadding - kEditInternalSpace;
461   const int kEdgeEditPadding =
462       LocationBarView::kEdgeItemPadding - kEditInternalSpace;
463   const int kBubbleVerticalPadding = (mode_ == POPUP) ?
464       -1 : kBubbleHorizontalPadding;
465 
466   // Start by reserving the padding at the right edge.
467   int entry_width = width() - kEdgeThickness - kEdgeItemPadding;
468 
469   // |location_icon_view_| is visible except when |ev_bubble_view_| or
470   // |selected_keyword_view_| are visible.
471   int location_icon_width = 0;
472   int ev_bubble_width = 0;
473   location_icon_view_->SetVisible(false);
474   ev_bubble_view_->SetVisible(false);
475   const string16 keyword(location_entry_->model()->keyword());
476   const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
477   const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint;
478   if (show_selected_keyword) {
479     // Assume the keyword might be hidden.
480     entry_width -= (kEdgeThickness + kEdgeEditPadding);
481   } else if (model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
482     ev_bubble_view_->SetVisible(true);
483     ev_bubble_view_->SetLabel(model_->GetEVCertName());
484     ev_bubble_width = ev_bubble_view_->GetPreferredSize().width();
485     // We'll adjust this width and take it out of |entry_width| below.
486   } else {
487     location_icon_view_->SetVisible(true);
488     location_icon_width = location_icon_view_->GetPreferredSize().width();
489     entry_width -= (kEdgeThickness + kEdgeItemPadding + location_icon_width +
490         kItemEditPadding);
491   }
492 
493   if (star_view_ && star_view_->IsVisible())
494     entry_width -= star_view_->GetPreferredSize().width() + kItemPadding;
495   for (PageActionViews::const_iterator i(page_action_views_.begin());
496        i != page_action_views_.end(); ++i) {
497     if ((*i)->IsVisible())
498       entry_width -= ((*i)->GetPreferredSize().width() + kItemPadding);
499   }
500   for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
501        i != content_setting_views_.end(); ++i) {
502     if ((*i)->IsVisible())
503       entry_width -= ((*i)->GetPreferredSize().width() + kItemPadding);
504   }
505   // The gap between the edit and whatever is to its right is shortened.
506   entry_width += kEditInternalSpace;
507 
508   // Size the EV bubble.  We do this after taking the star/page actions/content
509   // settings out of |entry_width| so we won't take too much space.
510   if (ev_bubble_width) {
511     // Try to elide the bubble to be no larger than half the total available
512     // space, but never elide it any smaller than 150 px.
513     static const int kMinElidedBubbleWidth = 150;
514     static const double kMaxBubbleFraction = 0.5;
515     const int total_padding =
516         kEdgeThickness + kBubbleHorizontalPadding + kItemEditPadding;
517     ev_bubble_width = std::min(ev_bubble_width, std::max(kMinElidedBubbleWidth,
518         static_cast<int>((entry_width - total_padding) * kMaxBubbleFraction)));
519     entry_width -= (total_padding + ev_bubble_width);
520   }
521 
522 #if defined(OS_WIN)
523   RECT formatting_rect;
524   location_entry_->GetRect(&formatting_rect);
525   RECT edit_bounds;
526   location_entry_->GetClientRect(&edit_bounds);
527   int max_edit_width = entry_width - formatting_rect.left -
528                        (edit_bounds.right - formatting_rect.right);
529 #else
530   int max_edit_width = entry_width;
531 #endif
532 
533   if (max_edit_width < 0)
534     return;
535   const int available_width = AvailableWidth(max_edit_width);
536 
537   const bool show_keyword_hint = !keyword.empty() && is_keyword_hint;
538   selected_keyword_view_->SetVisible(show_selected_keyword);
539   keyword_hint_view_->SetVisible(show_keyword_hint);
540   if (show_selected_keyword) {
541     if (selected_keyword_view_->keyword() != keyword) {
542       selected_keyword_view_->SetKeyword(keyword);
543       const TemplateURL* template_url =
544           profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
545       if (template_url && template_url->IsExtensionKeyword()) {
546         const SkBitmap& bitmap = profile_->GetExtensionService()->
547             GetOmniboxIcon(template_url->GetExtensionId());
548         selected_keyword_view_->SetImage(bitmap);
549         selected_keyword_view_->set_is_extension_icon(true);
550       } else {
551         selected_keyword_view_->SetImage(*ResourceBundle::GetSharedInstance().
552             GetBitmapNamed(IDR_OMNIBOX_SEARCH));
553         selected_keyword_view_->set_is_extension_icon(false);
554       }
555     }
556   } else if (show_keyword_hint) {
557     if (keyword_hint_view_->keyword() != keyword)
558       keyword_hint_view_->SetKeyword(keyword);
559   }
560 
561   // Lay out items to the right of the edit field.
562   int offset = width() - kEdgeThickness - kEdgeItemPadding;
563   if (star_view_ && star_view_->IsVisible()) {
564     int star_width = star_view_->GetPreferredSize().width();
565     offset -= star_width;
566     star_view_->SetBounds(offset, location_y, star_width, location_height);
567     offset -= kItemPadding;
568   }
569 
570   for (PageActionViews::const_iterator i(page_action_views_.begin());
571        i != page_action_views_.end(); ++i) {
572     if ((*i)->IsVisible()) {
573       int page_action_width = (*i)->GetPreferredSize().width();
574       offset -= page_action_width;
575       (*i)->SetBounds(offset, location_y, page_action_width, location_height);
576       offset -= kItemPadding;
577     }
578   }
579   // We use a reverse_iterator here because we're laying out the views from
580   // right to left but in the vector they're ordered left to right.
581   for (ContentSettingViews::const_reverse_iterator
582        i(content_setting_views_.rbegin()); i != content_setting_views_.rend();
583        ++i) {
584     if ((*i)->IsVisible()) {
585       int content_blocked_width = (*i)->GetPreferredSize().width();
586       offset -= content_blocked_width;
587       (*i)->SetBounds(offset, location_y, content_blocked_width,
588                       location_height);
589       offset -= kItemPadding;
590     }
591   }
592 
593   // Now lay out items to the left of the edit field.
594   if (location_icon_view_->IsVisible()) {
595     location_icon_view_->SetBounds(kEdgeThickness + kEdgeItemPadding,
596         location_y, location_icon_width, location_height);
597     offset = location_icon_view_->bounds().right() + kItemEditPadding;
598   } else if (ev_bubble_view_->IsVisible()) {
599     ev_bubble_view_->SetBounds(kEdgeThickness + kBubbleHorizontalPadding,
600         location_y + kBubbleVerticalPadding, ev_bubble_width,
601         ev_bubble_view_->GetPreferredSize().height());
602     offset = ev_bubble_view_->bounds().right() + kItemEditPadding;
603   } else {
604     offset = kEdgeThickness +
605         (show_selected_keyword ? kBubbleHorizontalPadding : kEdgeEditPadding);
606   }
607 
608   // Now lay out the edit field and views that autocollapse to give it more
609   // room.
610   gfx::Rect location_bounds(offset, location_y, entry_width, location_height);
611   if (show_selected_keyword) {
612     selected_keyword_view_->SetBounds(0, location_y + kBubbleVerticalPadding,
613         0, selected_keyword_view_->GetPreferredSize().height());
614     LayoutView(selected_keyword_view_, kItemEditPadding, available_width,
615                true, &location_bounds);
616     location_bounds.set_x(selected_keyword_view_->IsVisible() ?
617         (offset + selected_keyword_view_->width() + kItemEditPadding) :
618         (kEdgeThickness + kEdgeEditPadding));
619   } else if (show_keyword_hint) {
620     keyword_hint_view_->SetBounds(0, location_y, 0, location_height);
621     // Tricky: |entry_width| has already been enlarged by |kEditInternalSpace|.
622     // But if we add a trailing view, it needs to have that enlargement be to
623     // its left.  So we undo the enlargement, then include it in the padding for
624     // the added view.
625     location_bounds.Inset(0, 0, kEditInternalSpace, 0);
626     LayoutView(keyword_hint_view_, kItemEditPadding, available_width, false,
627                &location_bounds);
628     if (!keyword_hint_view_->IsVisible()) {
629       // Put back the enlargement that we undid above.
630       location_bounds.Inset(0, 0, -kEditInternalSpace, 0);
631     }
632   }
633 
634 #if defined(OS_WIN)
635   // Layout out the suggested text view right aligned to the location
636   // entry. Only show the suggested text if we can fit the text from one
637   // character before the end of the selection to the end of the text and the
638   // suggested text. If we can't it means either the suggested text is too big,
639   // or the user has scrolled.
640 
641   // TODO(sky): We could potentially combine this with the previous step to
642   // force using minimum size if necessary, but currently the chance of showing
643   // keyword hints and suggested text is minimal and we're not confident this
644   // is the right approach for suggested text.
645   if (suggested_text_view_) {
646     // TODO(sky): need to layout when the user changes caret position.
647     int suggested_text_width = suggested_text_view_->GetPreferredSize().width();
648     int vis_text_width = location_entry_->WidthOfTextAfterCursor();
649     if (vis_text_width + suggested_text_width > entry_width) {
650       // Hide the suggested text if the user has scrolled or we can't fit all
651       // the suggested text.
652       suggested_text_view_->SetBounds(0, 0, 0, 0);
653     } else {
654       int location_needed_width = location_entry_->TextWidth();
655       location_bounds.set_width(std::min(location_needed_width,
656                                          entry_width - suggested_text_width));
657       // TODO(sky): figure out why this needs the -1.
658       suggested_text_view_->SetBounds(location_bounds.right() - 1,
659                                       location_bounds.y(),
660                                       suggested_text_width,
661                                       location_bounds.height());
662     }
663   }
664 #endif
665 
666   location_entry_view_->SetBoundsRect(location_bounds);
667 }
668 
OnPaint(gfx::Canvas * canvas)669 void LocationBarView::OnPaint(gfx::Canvas* canvas) {
670   View::OnPaint(canvas);
671 
672   if (painter_.get()) {
673     painter_->Paint(width(), height(), canvas);
674   } else if (mode_ == POPUP) {
675     canvas->TileImageInt(*GetThemeProvider()->GetBitmapNamed(
676         IDR_LOCATIONBG_POPUPMODE_CENTER), 0, 0, 0, 0, width(), height());
677   }
678   // When used in the app launcher, don't draw a border, the LocationBarView has
679   // its own views::Border.
680 
681   // Draw the background color so that the graphical elements at the edges
682   // appear over the correct color.  (The edit draws its own background, so this
683   // isn't important for that.)
684   // TODO(pkasting): We need images that are transparent in the middle, so we
685   // can draw the border images over the background color instead of the
686   // reverse; this antialiases better (see comments in
687   // AutocompletePopupContentsView::OnPaint()).
688   gfx::Rect bounds(GetContentsBounds());
689   bounds.Inset(0, kVerticalEdgeThickness);
690   SkColor color(GetColor(ToolbarModel::NONE, BACKGROUND));
691   if (mode_ == NORMAL) {
692     SkPaint paint;
693     paint.setColor(color);
694     paint.setStyle(SkPaint::kFill_Style);
695     paint.setAntiAlias(true);
696     // The round corners of the omnibox match the round corners of the dropdown
697     // below, and all our other bubbles.
698     const SkScalar radius(SkIntToScalar(BubbleBorder::GetCornerRadius()));
699     bounds.Inset(kNormalHorizontalEdgeThickness, 0);
700     canvas->AsCanvasSkia()->drawRoundRect(gfx::RectToSkRect(bounds), radius,
701                                           radius, paint);
702   } else {
703     canvas->FillRectInt(color, bounds.x(), bounds.y(), bounds.width(),
704                         bounds.height());
705   }
706 
707   if (show_focus_rect_ && HasFocus()) {
708     gfx::Rect r = location_entry_view_->bounds();
709 #if defined(OS_WIN)
710     canvas->DrawFocusRect(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2);
711 #else
712     canvas->DrawFocusRect(r.x() - 1, r.y(), r.width() + 2, r.height());
713 #endif
714   }
715 }
716 
SetShowFocusRect(bool show)717 void LocationBarView::SetShowFocusRect(bool show) {
718   show_focus_rect_ = show;
719   SchedulePaint();
720 }
721 
SelectAll()722 void LocationBarView::SelectAll() {
723   location_entry_->SelectAll(true);
724 }
725 
726 #if defined(OS_WIN)
OnMousePressed(const views::MouseEvent & event)727 bool LocationBarView::OnMousePressed(const views::MouseEvent& event) {
728   UINT msg;
729   if (event.IsLeftMouseButton()) {
730     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
731         WM_LBUTTONDBLCLK : WM_LBUTTONDOWN;
732   } else if (event.IsMiddleMouseButton()) {
733     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
734         WM_MBUTTONDBLCLK : WM_MBUTTONDOWN;
735   } else if (event.IsRightMouseButton()) {
736     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
737         WM_RBUTTONDBLCLK : WM_RBUTTONDOWN;
738   } else {
739     NOTREACHED();
740     return false;
741   }
742   OnMouseEvent(event, msg);
743   return true;
744 }
745 
OnMouseDragged(const views::MouseEvent & event)746 bool LocationBarView::OnMouseDragged(const views::MouseEvent& event) {
747   OnMouseEvent(event, WM_MOUSEMOVE);
748   return true;
749 }
750 
OnMouseReleased(const views::MouseEvent & event)751 void LocationBarView::OnMouseReleased(const views::MouseEvent& event) {
752   UINT msg;
753   if (event.IsLeftMouseButton()) {
754     msg = WM_LBUTTONUP;
755   } else if (event.IsMiddleMouseButton()) {
756     msg = WM_MBUTTONUP;
757   } else if (event.IsRightMouseButton()) {
758     msg = WM_RBUTTONUP;
759   } else {
760     NOTREACHED();
761     return;
762   }
763   OnMouseEvent(event, msg);
764 }
765 
OnMouseCaptureLost()766 void LocationBarView::OnMouseCaptureLost() {
767   location_entry_->HandleExternalMsg(WM_CAPTURECHANGED, 0, CPoint());
768 }
769 #endif
770 
OnAutocompleteAccept(const GURL & url,WindowOpenDisposition disposition,PageTransition::Type transition,const GURL & alternate_nav_url)771 void LocationBarView::OnAutocompleteAccept(
772     const GURL& url,
773     WindowOpenDisposition disposition,
774     PageTransition::Type transition,
775     const GURL& alternate_nav_url) {
776   // WARNING: don't add an early return here. The calls after the if must
777   // happen.
778   if (url.is_valid()) {
779     location_input_ = UTF8ToWide(url.spec());
780     disposition_ = disposition;
781     transition_ = transition;
782 
783     if (command_updater_) {
784       if (!alternate_nav_url.is_valid()) {
785         command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
786       } else {
787         AlternateNavURLFetcher* fetcher =
788             new AlternateNavURLFetcher(alternate_nav_url);
789         // The AlternateNavURLFetcher will listen for the pending navigation
790         // notification that will be issued as a result of the "open URL." It
791         // will automatically install itself into that navigation controller.
792         command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
793         if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
794           // I'm not sure this should be reachable, but I'm not also sure enough
795           // that it shouldn't to stick in a NOTREACHED().  In any case, this is
796           // harmless.
797           delete fetcher;
798         } else {
799           // The navigation controller will delete the fetcher.
800         }
801       }
802     }
803   }
804 }
805 
OnChanged()806 void LocationBarView::OnChanged() {
807   location_icon_view_->SetImage(
808       ResourceBundle::GetSharedInstance().GetBitmapNamed(
809           location_entry_->GetIcon()));
810   location_icon_view_->ShowTooltip(!location_entry()->IsEditingOrEmpty());
811 
812   Layout();
813   SchedulePaint();
814 }
815 
OnSelectionBoundsChanged()816 void LocationBarView::OnSelectionBoundsChanged() {
817 #if defined(OS_WIN)
818   if (suggested_text_view_)
819     suggested_text_view_->StopAnimation();
820 #else
821   NOTREACHED();
822 #endif
823 }
824 
OnInputInProgress(bool in_progress)825 void LocationBarView::OnInputInProgress(bool in_progress) {
826   delegate_->OnInputInProgress(in_progress);
827 }
828 
OnKillFocus()829 void LocationBarView::OnKillFocus() {
830 }
831 
OnSetFocus()832 void LocationBarView::OnSetFocus() {
833   views::FocusManager* focus_manager = GetFocusManager();
834   if (!focus_manager) {
835     NOTREACHED();
836     return;
837   }
838   focus_manager->SetFocusedView(this);
839 }
840 
GetFavicon() const841 SkBitmap LocationBarView::GetFavicon() const {
842   return GetTabContentsFromDelegate(delegate_)->GetFavicon();
843 }
844 
GetTitle() const845 string16 LocationBarView::GetTitle() const {
846   return GetTabContentsFromDelegate(delegate_)->GetTitle();
847 }
848 
GetInstant()849 InstantController* LocationBarView::GetInstant() {
850   return delegate_->GetInstant();
851 }
852 
GetTabContentsWrapper() const853 TabContentsWrapper* LocationBarView::GetTabContentsWrapper() const {
854   return delegate_->GetTabContentsWrapper();
855 }
856 
AvailableWidth(int location_bar_width)857 int LocationBarView::AvailableWidth(int location_bar_width) {
858   return location_bar_width - location_entry_->TextWidth();
859 }
860 
LayoutView(views::View * view,int padding,int available_width,bool leading,gfx::Rect * bounds)861 void LocationBarView::LayoutView(views::View* view,
862                                  int padding,
863                                  int available_width,
864                                  bool leading,
865                                  gfx::Rect* bounds) {
866   DCHECK(view && bounds);
867   gfx::Size view_size = view->GetPreferredSize();
868   if ((view_size.width() + padding) > available_width)
869     view_size = view->GetMinimumSize();
870   int desired_width = view_size.width() + padding;
871   view->SetVisible(desired_width < bounds->width());
872   if (view->IsVisible()) {
873     view->SetBounds(
874         leading ? bounds->x() : (bounds->right() - view_size.width()),
875         view->y(), view_size.width(), view->height());
876     bounds->set_width(bounds->width() - desired_width);
877   }
878 }
879 
RefreshContentSettingViews()880 void LocationBarView::RefreshContentSettingViews() {
881   for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
882        i != content_setting_views_.end(); ++i) {
883     (*i)->UpdateFromTabContents(model_->input_in_progress() ? NULL :
884                                 GetTabContentsFromDelegate(delegate_));
885   }
886 }
887 
DeletePageActionViews()888 void LocationBarView::DeletePageActionViews() {
889   for (PageActionViews::const_iterator i(page_action_views_.begin());
890        i != page_action_views_.end(); ++i)
891     RemoveChildView(*i);
892   STLDeleteElements(&page_action_views_);
893 }
894 
RefreshPageActionViews()895 void LocationBarView::RefreshPageActionViews() {
896   if (mode_ != NORMAL)
897     return;
898 
899   ExtensionService* service = profile_->GetExtensionService();
900   if (!service)
901     return;
902 
903   std::map<ExtensionAction*, bool> old_visibility;
904   for (PageActionViews::const_iterator i(page_action_views_.begin());
905        i != page_action_views_.end(); ++i)
906     old_visibility[(*i)->image_view()->page_action()] = (*i)->IsVisible();
907 
908   // Remember the previous visibility of the page actions so that we can
909   // notify when this changes.
910   std::vector<ExtensionAction*> page_actions;
911   for (size_t i = 0; i < service->extensions()->size(); ++i) {
912     if (service->extensions()->at(i)->page_action())
913       page_actions.push_back(service->extensions()->at(i)->page_action());
914   }
915 
916   // On startup we sometimes haven't loaded any extensions. This makes sure
917   // we catch up when the extensions (and any page actions) load.
918   if (page_actions.size() != page_action_views_.size()) {
919     DeletePageActionViews();  // Delete the old views (if any).
920 
921     page_action_views_.resize(page_actions.size());
922 
923     // Add the page actions in reverse order, so that the child views are
924     // inserted in left-to-right order for accessibility.
925     for (int i = page_actions.size() - 1; i >= 0; --i) {
926       page_action_views_[i] = new PageActionWithBadgeView(
927           new PageActionImageView(this, profile_, page_actions[i]));
928       page_action_views_[i]->SetVisible(false);
929       AddChildViewAt(page_action_views_[i], GetIndexOf(star_view_));
930     }
931   }
932 
933   TabContents* contents = GetTabContentsFromDelegate(delegate_);
934   if (!page_action_views_.empty() && contents) {
935     GURL url = GURL(WideToUTF8(model_->GetText()));
936 
937     for (PageActionViews::const_iterator i(page_action_views_.begin());
938          i != page_action_views_.end(); ++i) {
939       (*i)->UpdateVisibility(model_->input_in_progress() ? NULL : contents,
940                              url);
941 
942       // Check if the visibility of the action changed and notify if it did.
943       ExtensionAction* action = (*i)->image_view()->page_action();
944       if (old_visibility.find(action) == old_visibility.end() ||
945           old_visibility[action] != (*i)->IsVisible()) {
946         NotificationService::current()->Notify(
947             NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
948             Source<ExtensionAction>(action),
949             Details<TabContents>(contents));
950       }
951     }
952   }
953 }
954 
955 #if defined(OS_WIN)
OnMouseEvent(const views::MouseEvent & event,UINT msg)956 void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) {
957   UINT flags = event.GetWindowsFlags();
958   gfx::Point screen_point(event.location());
959   ConvertPointToScreen(this, &screen_point);
960   location_entry_->HandleExternalMsg(msg, flags, screen_point.ToPOINT());
961 }
962 #endif
963 
ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type)964 void LocationBarView::ShowFirstRunBubbleInternal(
965     FirstRun::BubbleType bubble_type) {
966 #if defined(OS_WIN)  // First run bubble doesn't make sense for Chrome OS.
967   // Point at the start of the edit control; adjust to look as good as possible.
968   const int kXOffset = kNormalHorizontalEdgeThickness + kEdgeItemPadding +
969       ResourceBundle::GetSharedInstance().GetBitmapNamed(
970       IDR_OMNIBOX_HTTP)->width() + kItemPadding;
971   const int kYOffset = -(kVerticalEdgeThickness + 2);
972   gfx::Point origin(location_entry_view_->bounds().x() + kXOffset,
973                     y() + height() + kYOffset);
974   // If the UI layout is RTL, the coordinate system is not transformed and
975   // therefore we need to adjust the X coordinate so that bubble appears on the
976   // right hand side of the location bar.
977   if (base::i18n::IsRTL())
978     origin.set_x(width() - origin.x());
979   views::View::ConvertPointToScreen(this, &origin);
980   FirstRunBubble::Show(profile_, GetWidget(), gfx::Rect(origin, gfx::Size()),
981                        BubbleBorder::TOP_LEFT, bubble_type);
982 #endif
983 }
984 
GetClassName() const985 std::string LocationBarView::GetClassName() const {
986   return kViewClassName;
987 }
988 
SkipDefaultKeyEventProcessing(const views::KeyEvent & event)989 bool LocationBarView::SkipDefaultKeyEventProcessing(
990     const views::KeyEvent& event) {
991 #if defined(OS_WIN)
992   if (views::FocusManager::IsTabTraversalKeyEvent(event)) {
993     if (HasValidSuggestText()) {
994       // Return true so that the edit sees the tab and commits the suggestion.
995       return true;
996     }
997     if (keyword_hint_view_->IsVisible() && !event.IsShiftDown()) {
998       // Return true so the edit gets the tab event and enters keyword mode.
999       return true;
1000     }
1001 
1002     // If the caret is not at the end, then tab moves the caret to the end.
1003     if (!location_entry_->IsCaretAtEnd())
1004       return true;
1005 
1006     // Tab while showing instant commits instant immediately.
1007     // Return true so that focus traversal isn't attempted. The edit ends
1008     // up doing nothing in this case.
1009     if (location_entry_->model()->AcceptCurrentInstantPreview())
1010       return true;
1011   }
1012 
1013   return location_entry_->SkipDefaultKeyEventProcessing(event);
1014 #else
1015   // This method is not used for Linux ports. See FocusManager::OnKeyEvent() in
1016   // src/views/focus/focus_manager.cc for details.
1017   return false;
1018 #endif
1019 }
1020 
GetAccessibleState(ui::AccessibleViewState * state)1021 void LocationBarView::GetAccessibleState(ui::AccessibleViewState* state) {
1022   state->role = ui::AccessibilityTypes::ROLE_GROUPING;
1023   state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
1024   state->value = location_entry_->GetText();
1025 
1026   string16::size_type entry_start;
1027   string16::size_type entry_end;
1028   location_entry_->GetSelectionBounds(&entry_start, &entry_end);
1029   state->selection_start = entry_start;
1030   state->selection_end = entry_end;
1031 }
1032 
WriteDragDataForView(views::View * sender,const gfx::Point & press_pt,OSExchangeData * data)1033 void LocationBarView::WriteDragDataForView(views::View* sender,
1034                                            const gfx::Point& press_pt,
1035                                            OSExchangeData* data) {
1036   DCHECK_NE(GetDragOperationsForView(sender, press_pt),
1037             ui::DragDropTypes::DRAG_NONE);
1038 
1039   TabContents* tab_contents = GetTabContentsFromDelegate(delegate_);
1040   DCHECK(tab_contents);
1041   drag_utils::SetURLAndDragImage(tab_contents->GetURL(),
1042                                  UTF16ToWideHack(tab_contents->GetTitle()),
1043                                  tab_contents->GetFavicon(), data);
1044 }
1045 
GetDragOperationsForView(views::View * sender,const gfx::Point & p)1046 int LocationBarView::GetDragOperationsForView(views::View* sender,
1047                                               const gfx::Point& p) {
1048   DCHECK((sender == location_icon_view_) || (sender == ev_bubble_view_));
1049   TabContents* tab_contents = GetTabContentsFromDelegate(delegate_);
1050   return (tab_contents && tab_contents->GetURL().is_valid() &&
1051           !location_entry()->IsEditingOrEmpty()) ?
1052       (ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK) :
1053       ui::DragDropTypes::DRAG_NONE;
1054 }
1055 
CanStartDragForView(View * sender,const gfx::Point & press_pt,const gfx::Point & p)1056 bool LocationBarView::CanStartDragForView(View* sender,
1057                                           const gfx::Point& press_pt,
1058                                           const gfx::Point& p) {
1059   return true;
1060 }
1061 
1062 ////////////////////////////////////////////////////////////////////////////////
1063 // LocationBarView, LocationBar implementation:
1064 
ShowFirstRunBubble(FirstRun::BubbleType bubble_type)1065 void LocationBarView::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
1066   // Wait until search engines have loaded to show the first run bubble.
1067   if (!profile_->GetTemplateURLModel()->loaded()) {
1068     bubble_type_ = bubble_type;
1069     template_url_model_ = profile_->GetTemplateURLModel();
1070     template_url_model_->AddObserver(this);
1071     template_url_model_->Load();
1072     return;
1073   }
1074   ShowFirstRunBubbleInternal(bubble_type);
1075 }
1076 
SetSuggestedText(const string16 & text,InstantCompleteBehavior behavior)1077 void LocationBarView::SetSuggestedText(const string16& text,
1078                                        InstantCompleteBehavior behavior) {
1079   location_entry_->model()->SetSuggestedText(text, behavior);
1080 }
1081 
GetInputString() const1082 std::wstring LocationBarView::GetInputString() const {
1083   return location_input_;
1084 }
1085 
GetWindowOpenDisposition() const1086 WindowOpenDisposition LocationBarView::GetWindowOpenDisposition() const {
1087   return disposition_;
1088 }
1089 
GetPageTransition() const1090 PageTransition::Type LocationBarView::GetPageTransition() const {
1091   return transition_;
1092 }
1093 
AcceptInput()1094 void LocationBarView::AcceptInput() {
1095   location_entry_->model()->AcceptInput(CURRENT_TAB, false);
1096 }
1097 
FocusLocation(bool select_all)1098 void LocationBarView::FocusLocation(bool select_all) {
1099   location_entry_->SetFocus();
1100   if (select_all)
1101     location_entry_->SelectAll(true);
1102 }
1103 
FocusSearch()1104 void LocationBarView::FocusSearch() {
1105   location_entry_->SetFocus();
1106   location_entry_->SetForcedQuery();
1107 }
1108 
SaveStateToContents(TabContents * contents)1109 void LocationBarView::SaveStateToContents(TabContents* contents) {
1110   location_entry_->SaveStateToTab(contents);
1111 }
1112 
Revert()1113 void LocationBarView::Revert() {
1114   location_entry_->RevertAll();
1115 }
1116 
location_entry() const1117 const AutocompleteEditView* LocationBarView::location_entry() const {
1118   return location_entry_.get();
1119 }
1120 
location_entry()1121 AutocompleteEditView* LocationBarView::location_entry() {
1122   return location_entry_.get();
1123 }
1124 
GetLocationBarForTesting()1125 LocationBarTesting* LocationBarView::GetLocationBarForTesting() {
1126   return this;
1127 }
1128 
PageActionCount()1129 int LocationBarView::PageActionCount() {
1130   return page_action_views_.size();
1131 }
1132 
PageActionVisibleCount()1133 int LocationBarView::PageActionVisibleCount() {
1134   int result = 0;
1135   for (size_t i = 0; i < page_action_views_.size(); i++) {
1136     if (page_action_views_[i]->IsVisible())
1137       ++result;
1138   }
1139   return result;
1140 }
1141 
GetPageAction(size_t index)1142 ExtensionAction* LocationBarView::GetPageAction(size_t index) {
1143   if (index < page_action_views_.size())
1144     return page_action_views_[index]->image_view()->page_action();
1145 
1146   NOTREACHED();
1147   return NULL;
1148 }
1149 
GetVisiblePageAction(size_t index)1150 ExtensionAction* LocationBarView::GetVisiblePageAction(size_t index) {
1151   size_t current = 0;
1152   for (size_t i = 0; i < page_action_views_.size(); ++i) {
1153     if (page_action_views_[i]->IsVisible()) {
1154       if (current == index)
1155         return page_action_views_[i]->image_view()->page_action();
1156 
1157       ++current;
1158     }
1159   }
1160 
1161   NOTREACHED();
1162   return NULL;
1163 }
1164 
TestPageActionPressed(size_t index)1165 void LocationBarView::TestPageActionPressed(size_t index) {
1166   size_t current = 0;
1167   for (size_t i = 0; i < page_action_views_.size(); ++i) {
1168     if (page_action_views_[i]->IsVisible()) {
1169       if (current == index) {
1170         const int kLeftMouseButton = 1;
1171         page_action_views_[i]->image_view()->ExecuteAction(kLeftMouseButton,
1172             false);  // inspect_with_devtools
1173         return;
1174       }
1175       ++current;
1176     }
1177   }
1178 
1179   NOTREACHED();
1180 }
1181 
OnTemplateURLModelChanged()1182 void LocationBarView::OnTemplateURLModelChanged() {
1183   template_url_model_->RemoveObserver(this);
1184   template_url_model_ = NULL;
1185   // If the browser is no longer active, let's not show the info bubble, as this
1186   // would make the browser the active window again.
1187   if (location_entry_view_ && location_entry_view_->GetWidget()->IsActive())
1188     ShowFirstRunBubble(bubble_type_);
1189 }
1190 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)1191 void LocationBarView::Observe(NotificationType type,
1192                               const NotificationSource& source,
1193                               const NotificationDetails& details) {
1194   if (type.value == NotificationType::PREF_CHANGED) {
1195     std::string* name = Details<std::string>(details).ptr();
1196     if (*name == prefs::kEditBookmarksEnabled)
1197       Update(NULL);
1198   }
1199 }
1200 
1201 #if defined(OS_WIN)
HasValidSuggestText() const1202 bool LocationBarView::HasValidSuggestText() const {
1203   return suggested_text_view_ && !suggested_text_view_->size().IsEmpty() &&
1204       !suggested_text_view_->GetText().empty();
1205 }
1206 #endif
1207