Home | History | Annotate | Download | only in location_bar
      1 // Copyright (c) 2012 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 #include <algorithm>
      8 #include <map>
      9 
     10 #include "base/command_line.h"
     11 #include "base/i18n/rtl.h"
     12 #include "base/prefs/pref_service.h"
     13 #include "base/stl_util.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "chrome/app/chrome_command_ids.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/command_updater.h"
     18 #include "chrome/browser/defaults.h"
     19 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
     20 #include "chrome/browser/extensions/location_bar_controller.h"
     21 #include "chrome/browser/extensions/script_bubble_controller.h"
     22 #include "chrome/browser/extensions/tab_helper.h"
     23 #include "chrome/browser/favicon/favicon_tab_helper.h"
     24 #include "chrome/browser/profiles/profile.h"
     25 #include "chrome/browser/search_engines/template_url.h"
     26 #include "chrome/browser/search_engines/template_url_service.h"
     27 #include "chrome/browser/search_engines/template_url_service_factory.h"
     28 #include "chrome/browser/ui/browser.h"
     29 #include "chrome/browser/ui/browser_finder.h"
     30 #include "chrome/browser/ui/browser_instant_controller.h"
     31 #include "chrome/browser/ui/browser_window.h"
     32 #include "chrome/browser/ui/omnibox/alternate_nav_url_fetcher.h"
     33 #include "chrome/browser/ui/omnibox/location_bar_util.h"
     34 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
     35 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
     36 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     37 #include "chrome/browser/ui/view_ids.h"
     38 #include "chrome/browser/ui/views/bookmarks/bookmark_prompt_view.h"
     39 #include "chrome/browser/ui/views/browser_dialogs.h"
     40 #include "chrome/browser/ui/views/extensions/extension_popup.h"
     41 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
     42 #include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
     43 #include "chrome/browser/ui/views/location_bar/generated_credit_card_view.h"
     44 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
     45 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
     46 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
     47 #include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
     48 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
     49 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
     50 #include "chrome/browser/ui/views/location_bar/script_bubble_icon_view.h"
     51 #include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
     52 #include "chrome/browser/ui/views/location_bar/star_view.h"
     53 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
     54 #include "chrome/browser/ui/views/location_bar/zoom_view.h"
     55 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
     56 #include "chrome/browser/ui/views/omnibox/omnibox_views.h"
     57 #include "chrome/browser/ui/zoom/zoom_controller.h"
     58 #include "chrome/common/extensions/feature_switch.h"
     59 #include "chrome/common/pref_names.h"
     60 #include "content/public/browser/notification_service.h"
     61 #include "content/public/browser/render_widget_host_view.h"
     62 #include "content/public/browser/web_contents.h"
     63 #include "grit/generated_resources.h"
     64 #include "grit/theme_resources.h"
     65 #include "ui/base/accessibility/accessible_view_state.h"
     66 #include "ui/base/dragdrop/drag_drop_types.h"
     67 #include "ui/base/events/event.h"
     68 #include "ui/base/l10n/l10n_util.h"
     69 #include "ui/base/layout.h"
     70 #include "ui/base/resource/resource_bundle.h"
     71 #include "ui/base/theme_provider.h"
     72 #include "ui/gfx/canvas.h"
     73 #include "ui/gfx/color_utils.h"
     74 #include "ui/gfx/image/image.h"
     75 #include "ui/gfx/image/image_skia_operations.h"
     76 #include "ui/gfx/skia_util.h"
     77 #include "ui/native_theme/native_theme.h"
     78 #include "ui/views/background.h"
     79 #include "ui/views/border.h"
     80 #include "ui/views/button_drag_utils.h"
     81 #include "ui/views/controls/button/image_button.h"
     82 #include "ui/views/controls/label.h"
     83 #include "ui/views/controls/textfield/textfield.h"
     84 #include "ui/views/widget/widget.h"
     85 #include "ui/views/window/non_client_view.h"
     86 
     87 #if defined(OS_WIN)
     88 #include "base/win/scoped_hdc.h"
     89 #include "base/win/scoped_select_object.h"
     90 #include "ui/native_theme/native_theme_win.h"
     91 #endif
     92 
     93 #if defined(OS_WIN) && !defined(USE_AURA)
     94 #include "chrome/browser/ui/views/omnibox/omnibox_view_win.h"
     95 #endif
     96 
     97 #if !defined(OS_CHROMEOS)
     98 #include "chrome/browser/ui/views/first_run_bubble.h"
     99 #endif
    100 
    101 #if defined(USE_AURA)
    102 #include "ui/compositor/layer.h"
    103 #include "ui/compositor/scoped_layer_animation_settings.h"
    104 #endif
    105 
    106 using content::WebContents;
    107 using views::View;
    108 
    109 
    110 namespace {
    111 
    112 Browser* GetBrowserFromDelegate(LocationBarView::Delegate* delegate) {
    113   WebContents* contents = delegate->GetWebContents();
    114   return contents ? chrome::FindBrowserWithWebContents(contents) : NULL;
    115 }
    116 
    117 // Given a containing |height| and a base |font_list|, shrinks the fonts until
    118 // the primary font will fit within |height| while having its cap height
    119 // vertically centered.  Returns the |font_y_offset| needed to produce this
    120 // centering.
    121 void CalculateFontAndOffsetForHeight(int height,
    122                                      gfx::FontList* font_list,
    123                                      int* font_y_offset) {
    124 #if defined(OS_WIN)
    125   base::win::ScopedGetDC screen_dc(NULL);
    126 #endif
    127 
    128   while (true) {
    129     // TODO(pkasting): Expand the gfx::Font metrics (and underlying Skia
    130     // metrics) enough to expose the cap height directly.
    131 #if defined(OS_WIN)
    132     const gfx::Font& font = font_list->GetPrimaryFont();
    133     base::win::ScopedSelectObject font_in_dc(screen_dc, font.GetNativeFont());
    134     TEXTMETRIC tm = {0};
    135     GetTextMetrics(screen_dc, &tm);
    136     int cap_height = font.GetBaseline() - tm.tmInternalLeading;
    137     *font_y_offset = ((height - cap_height) / 2) - tm.tmInternalLeading;
    138 #else
    139     // Without cap height available, we fall back to centering the full height.
    140     *font_y_offset = (height - font_list->GetHeight()) / 2;
    141 #endif
    142 
    143     const int font_size = font_list->GetFontSize();
    144     if (((*font_y_offset >= 0) &&
    145          ((*font_y_offset + font_list->GetHeight()) <= height)) ||
    146         (font_size <= 1))
    147       return;
    148     *font_list = font_list->DeriveFontListWithSize(font_size - 1);
    149   }
    150 }
    151 
    152 }  // namespace
    153 
    154 
    155 // LocationBarView -----------------------------------------------------------
    156 
    157 // static
    158 const int LocationBarView::kNormalEdgeThickness = 2;
    159 const int LocationBarView::kPopupEdgeThickness = 1;
    160 const int LocationBarView::kIconInternalPadding = 2;
    161 const int LocationBarView::kBubblePadding = 1;
    162 const char LocationBarView::kViewClassName[] = "LocationBarView";
    163 
    164 LocationBarView::LocationBarView(Browser* browser,
    165                                  Profile* profile,
    166                                  CommandUpdater* command_updater,
    167                                  ToolbarModel* model,
    168                                  Delegate* delegate,
    169                                  bool is_popup_mode)
    170     : browser_(browser),
    171       profile_(profile),
    172       command_updater_(command_updater),
    173       model_(model),
    174       delegate_(delegate),
    175       disposition_(CURRENT_TAB),
    176       transition_(content::PageTransitionFromInt(
    177           content::PAGE_TRANSITION_TYPED |
    178           content::PAGE_TRANSITION_FROM_ADDRESS_BAR)),
    179       location_icon_view_(NULL),
    180       ev_bubble_view_(NULL),
    181       location_entry_view_(NULL),
    182       ime_inline_autocomplete_view_(NULL),
    183       selected_keyword_view_(NULL),
    184       suggested_text_view_(NULL),
    185       keyword_hint_view_(NULL),
    186       mic_search_view_(NULL),
    187       zoom_view_(NULL),
    188       generated_credit_card_view_(NULL),
    189       open_pdf_in_reader_view_(NULL),
    190       script_bubble_icon_view_(NULL),
    191       star_view_(NULL),
    192       is_popup_mode_(is_popup_mode),
    193       show_focus_rect_(false),
    194       template_url_service_(NULL),
    195       animation_offset_(0),
    196       weak_ptr_factory_(this) {
    197   if (!views::Textfield::IsViewsTextfieldEnabled())
    198     set_id(VIEW_ID_OMNIBOX);
    199 
    200   const int kOmniboxBorderImages[] = IMAGE_GRID(IDR_OMNIBOX_BORDER);
    201   const int kOmniboxPopupImages[] = IMAGE_GRID(IDR_OMNIBOX_POPUP_BORDER);
    202   background_border_painter_.reset(
    203       views::Painter::CreateImageGridPainter(
    204           is_popup_mode_ ? kOmniboxPopupImages : kOmniboxBorderImages));
    205 #if defined(OS_CHROMEOS)
    206   if (!is_popup_mode_) {
    207     const int kOmniboxFillingImages[] = IMAGE_GRID(IDR_OMNIBOX_FILLING);
    208     background_filling_painter_.reset(
    209         views::Painter::CreateImageGridPainter(kOmniboxFillingImages));
    210   }
    211 #endif
    212 
    213   edit_bookmarks_enabled_.Init(
    214       prefs::kEditBookmarksEnabled,
    215       profile_->GetPrefs(),
    216       base::Bind(&LocationBarView::Update,
    217                  base::Unretained(this),
    218                  static_cast<content::WebContents*>(NULL)));
    219 
    220   if (browser_)
    221     browser_->search_model()->AddObserver(this);
    222 }
    223 
    224 LocationBarView::~LocationBarView() {
    225   if (template_url_service_)
    226     template_url_service_->RemoveObserver(this);
    227   if (browser_)
    228     browser_->search_model()->RemoveObserver(this);
    229 }
    230 
    231 // static
    232 void LocationBarView::InitTouchableLocationBarChildView(views::View* view) {
    233   int horizontal_padding = GetBuiltInHorizontalPaddingForChildViews();
    234   if (horizontal_padding != 0) {
    235     view->set_border(views::Border::CreateEmptyBorder(
    236         3, horizontal_padding, 3, horizontal_padding));
    237   }
    238 }
    239 
    240 void LocationBarView::Init() {
    241   // We need to be in a Widget, otherwise GetNativeTheme() may change and we're
    242   // not prepared for that.
    243   DCHECK(GetWidget());
    244 
    245   location_icon_view_ = new LocationIconView(this);
    246   location_icon_view_->set_drag_controller(this);
    247   AddChildView(location_icon_view_);
    248 
    249   // Determine the main font.
    250   gfx::FontList font_list = ResourceBundle::GetSharedInstance().GetFontList(
    251       ResourceBundle::BaseFont);
    252   const int current_font_size = font_list.GetFontSize();
    253   const int desired_font_size = browser_defaults::kOmniboxFontPixelSize;
    254   if (current_font_size < desired_font_size)
    255     font_list = font_list.DeriveFontListWithSize(desired_font_size);
    256   // Shrink large fonts to make them fit.
    257   // TODO(pkasting): Stretch the location bar instead in this case.
    258   int location_height = GetInternalHeight(true);
    259   int font_y_offset;
    260   CalculateFontAndOffsetForHeight(location_height, &font_list, &font_y_offset);
    261   const gfx::Font& font = font_list.GetPrimaryFont();
    262 
    263   // Determine the font for use inside the bubbles.
    264   gfx::FontList bubble_font_list(font_list);
    265   int bubble_font_y_offset;
    266   // The bubble background images have 1 px thick edges, which we don't want to
    267   // overlap.
    268   const int kBubbleInteriorVerticalPadding = 1;
    269   CalculateFontAndOffsetForHeight(
    270       location_height - ((kBubblePadding + kBubbleInteriorVerticalPadding) * 2),
    271       &bubble_font_list, &bubble_font_y_offset);
    272   bubble_font_y_offset += kBubbleInteriorVerticalPadding;
    273   const gfx::Font& bubble_font = font_list.GetPrimaryFont();
    274 
    275   const SkColor background_color =
    276       GetColor(ToolbarModel::NONE, LocationBarView::BACKGROUND);
    277   ev_bubble_view_ = new EVBubbleView(
    278       bubble_font, bubble_font_y_offset,
    279       GetColor(ToolbarModel::EV_SECURE, SECURITY_TEXT), background_color, this);
    280   ev_bubble_view_->set_drag_controller(this);
    281   AddChildView(ev_bubble_view_);
    282 
    283   // Initialize the Omnibox view.
    284   location_entry_.reset(CreateOmniboxView(this, model_, profile_,
    285       command_updater_, is_popup_mode_, this, font_list, font_y_offset));
    286   SetLocationEntryFocusable(true);
    287   location_entry_view_ = location_entry_->AddToView(this);
    288 
    289   // Initialize the inline autocomplete view which is visible only when IME is
    290   // turned on.  Use the same font with the omnibox and highlighted background.
    291   ime_inline_autocomplete_view_ = new views::Label(string16(), font);
    292   {
    293     // views::Label (|ime_inline_autocomplete_view_|) supports only gfx::Font
    294     // and ignores the rest of fonts but the first in |font_list| while
    295     // views::Textfield (|location_entry_view_|) supports gfx::FontList and
    296     // layouts text based on all fonts in the list.  Thus the font height and
    297     // baseline can be different between them.  We add padding to align them
    298     // on the same baseline.
    299     // TODO(yukishiino): Remove this hack once views::Label supports
    300     // gfx::FontList.
    301     const int baseline_diff = location_entry_view_->GetBaseline() -
    302         ime_inline_autocomplete_view_->GetBaseline();
    303     ime_inline_autocomplete_view_->set_border(
    304         views::Border::CreateEmptyBorder(
    305             font_y_offset + baseline_diff, 0, 0, 0));
    306   }
    307   ime_inline_autocomplete_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    308   ime_inline_autocomplete_view_->SetAutoColorReadabilityEnabled(false);
    309   ime_inline_autocomplete_view_->set_background(
    310       views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
    311           ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused)));
    312   ime_inline_autocomplete_view_->SetEnabledColor(
    313       GetNativeTheme()->GetSystemColor(
    314           ui::NativeTheme::kColorId_TextfieldSelectionColor));
    315   ime_inline_autocomplete_view_->SetVisible(false);
    316   AddChildView(ime_inline_autocomplete_view_);
    317 
    318   const SkColor text_color = GetColor(ToolbarModel::NONE, TEXT);
    319   selected_keyword_view_ = new SelectedKeywordView(
    320       bubble_font, bubble_font_y_offset, text_color, background_color,
    321       profile_);
    322   AddChildView(selected_keyword_view_);
    323 
    324   suggested_text_view_ = new views::Label(string16(), font);
    325   suggested_text_view_->set_border(
    326       views::Border::CreateEmptyBorder(font_y_offset, 0, 0, 0));
    327   suggested_text_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    328   suggested_text_view_->SetAutoColorReadabilityEnabled(false);
    329   suggested_text_view_->SetEnabledColor(GetColor(
    330       ToolbarModel::NONE, LocationBarView::DEEMPHASIZED_TEXT));
    331   suggested_text_view_->SetVisible(false);
    332   AddChildView(suggested_text_view_);
    333 
    334   keyword_hint_view_ = new KeywordHintView(
    335       profile_, font, font_y_offset,
    336       GetColor(ToolbarModel::NONE, LocationBarView::DEEMPHASIZED_TEXT),
    337       background_color);
    338   AddChildView(keyword_hint_view_);
    339 
    340   mic_search_view_ = new views::ImageButton(this);
    341   mic_search_view_->set_id(VIEW_ID_MIC_SEARCH_BUTTON);
    342   mic_search_view_->set_accessibility_focusable(true);
    343   mic_search_view_->SetTooltipText(
    344       l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH));
    345   mic_search_view_->SetImage(
    346       views::Button::STATE_NORMAL,
    347       ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
    348           IDR_OMNIBOX_MIC_SEARCH));
    349   mic_search_view_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
    350                                       views::ImageButton::ALIGN_MIDDLE);
    351   mic_search_view_->SetVisible(false);
    352   InitTouchableLocationBarChildView(mic_search_view_);
    353   AddChildView(mic_search_view_);
    354 
    355   for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
    356     ContentSettingImageView* content_blocked_view =
    357         new ContentSettingImageView(static_cast<ContentSettingsType>(i), this,
    358                                     bubble_font, bubble_font_y_offset,
    359                                     text_color, background_color);
    360     content_setting_views_.push_back(content_blocked_view);
    361     content_blocked_view->SetVisible(false);
    362     AddChildView(content_blocked_view);
    363   }
    364 
    365   generated_credit_card_view_ = new GeneratedCreditCardView(model_, delegate_);
    366   AddChildView(generated_credit_card_view_);
    367 
    368   zoom_view_ = new ZoomView(model_, delegate_);
    369   zoom_view_->set_id(VIEW_ID_ZOOM_BUTTON);
    370   AddChildView(zoom_view_);
    371 
    372   open_pdf_in_reader_view_ = new OpenPDFInReaderView(this);
    373   AddChildView(open_pdf_in_reader_view_);
    374 
    375   script_bubble_icon_view_ = new ScriptBubbleIconView(delegate());
    376   script_bubble_icon_view_->SetVisible(false);
    377   AddChildView(script_bubble_icon_view_);
    378 
    379   star_view_ = new StarView(command_updater_);
    380   star_view_->SetVisible(false);
    381   AddChildView(star_view_);
    382 
    383   registrar_.Add(this,
    384                  chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED,
    385                  content::Source<Profile>(profile_));
    386 
    387   // Initialize the location entry. We do this to avoid a black flash which is
    388   // visible when the location entry has just been initialized.
    389   Update(NULL);
    390 
    391   OnChanged();
    392 }
    393 
    394 bool LocationBarView::IsInitialized() const {
    395   return location_entry_view_ != NULL;
    396 }
    397 
    398 SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level,
    399                                   ColorKind kind) const {
    400   const ui::NativeTheme* native_theme = GetNativeTheme();
    401   switch (kind) {
    402     case BACKGROUND:
    403 #if defined(OS_CHROMEOS)
    404       // Chrome OS requires a transparent omnibox background color.
    405       return SkColorSetARGB(0, 255, 255, 255);
    406 #else
    407       return native_theme->GetSystemColor(
    408           ui::NativeTheme::kColorId_TextfieldDefaultBackground);
    409 #endif
    410 
    411     case TEXT:
    412       return native_theme->GetSystemColor(
    413           ui::NativeTheme::kColorId_TextfieldDefaultColor);
    414 
    415     case SELECTED_TEXT:
    416       return native_theme->GetSystemColor(
    417           ui::NativeTheme::kColorId_TextfieldSelectionColor);
    418 
    419     case DEEMPHASIZED_TEXT:
    420       return color_utils::AlphaBlend(
    421           GetColor(security_level, TEXT),
    422           GetColor(security_level, BACKGROUND),
    423           128);
    424 
    425     case SECURITY_TEXT: {
    426       SkColor color;
    427       switch (security_level) {
    428         case ToolbarModel::EV_SECURE:
    429         case ToolbarModel::SECURE:
    430           color = SkColorSetRGB(7, 149, 0);
    431           break;
    432 
    433         case ToolbarModel::SECURITY_WARNING:
    434         case ToolbarModel::SECURITY_POLICY_WARNING:
    435           return GetColor(security_level, DEEMPHASIZED_TEXT);
    436           break;
    437 
    438         case ToolbarModel::SECURITY_ERROR:
    439           color = SkColorSetRGB(162, 0, 0);
    440           break;
    441 
    442         default:
    443           NOTREACHED();
    444           return GetColor(security_level, TEXT);
    445       }
    446       return color_utils::GetReadableColor(
    447           color, GetColor(security_level, BACKGROUND));
    448     }
    449 
    450     default:
    451       NOTREACHED();
    452       return GetColor(security_level, TEXT);
    453   }
    454 }
    455 
    456 void LocationBarView::GetOmniboxPopupPositioningInfo(
    457     gfx::Point* top_left_screen_coord,
    458     int* popup_width,
    459     int* left_margin,
    460     int* right_margin) {
    461   // Because the popup might appear atop the attached bookmark bar, there won't
    462   // necessarily be a client edge separating it from the rest of the toolbar.
    463   // Therefore we position the popup high enough so it can draw its own client
    464   // edge at the top, in the same place the toolbar would normally draw the
    465   // client edge.
    466   *top_left_screen_coord = gfx::Point(
    467       0,
    468       parent()->height() - views::NonClientFrameView::kClientEdgeThickness);
    469   views::View::ConvertPointToScreen(parent(), top_left_screen_coord);
    470   *popup_width = parent()->width();
    471 
    472   gfx::Rect location_bar_bounds(bounds());
    473   location_bar_bounds.Inset(kNormalEdgeThickness, 0);
    474   *left_margin = location_bar_bounds.x();
    475   *right_margin = *popup_width - location_bar_bounds.right();
    476 }
    477 
    478 // static
    479 int LocationBarView::GetItemPadding() {
    480   const int kTouchItemPadding = 8;
    481   if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH)
    482     return kTouchItemPadding;
    483 
    484   const int kDesktopScriptBadgeItemPadding = 9;
    485   const int kDesktopItemPadding = 3;
    486   return extensions::FeatureSwitch::script_badges()->IsEnabled() ?
    487       kDesktopScriptBadgeItemPadding : kDesktopItemPadding;
    488 }
    489 
    490 // DropdownBarHostDelegate
    491 void LocationBarView::SetFocusAndSelection(bool select_all) {
    492   FocusLocation(select_all);
    493 }
    494 
    495 void LocationBarView::SetAnimationOffset(int offset) {
    496   animation_offset_ = offset;
    497 }
    498 
    499 void LocationBarView::Update(const WebContents* tab_for_state_restoring) {
    500   mic_search_view_->SetVisible(
    501       !model_->GetInputInProgress() && browser_ &&
    502       browser_->search_model()->voice_search_supported());
    503   RefreshContentSettingViews();
    504   generated_credit_card_view_->Update();
    505   ZoomBubbleView::CloseBubble();
    506   RefreshZoomView();
    507   RefreshPageActionViews();
    508   RefreshScriptBubble();
    509   open_pdf_in_reader_view_->Update(
    510       model_->GetInputInProgress() ? NULL : GetWebContents());
    511 
    512   bool star_enabled =
    513       browser_defaults::bookmarks_enabled && !is_popup_mode_ && star_view_ &&
    514       !model_->GetInputInProgress() && edit_bookmarks_enabled_.GetValue();
    515 
    516   command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE, star_enabled);
    517   command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE_FROM_STAR,
    518                                          star_enabled);
    519   if (star_view_)
    520     star_view_->SetVisible(star_enabled);
    521 
    522   location_entry_->Update(tab_for_state_restoring);
    523 
    524   OnChanged();
    525 }
    526 
    527 void LocationBarView::UpdateContentSettingsIcons() {
    528   RefreshContentSettingViews();
    529 
    530   Layout();
    531   SchedulePaint();
    532 }
    533 
    534 void LocationBarView::UpdatePageActions() {
    535   size_t count_before = page_action_views_.size();
    536   RefreshPageActionViews();
    537   RefreshScriptBubble();
    538   if (page_action_views_.size() != count_before) {
    539     content::NotificationService::current()->Notify(
    540         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
    541         content::Source<LocationBar>(this),
    542         content::NotificationService::NoDetails());
    543   }
    544 
    545   Layout();
    546   SchedulePaint();
    547 }
    548 
    549 void LocationBarView::InvalidatePageActions() {
    550   size_t count_before = page_action_views_.size();
    551   DeletePageActionViews();
    552   if (page_action_views_.size() != count_before) {
    553     content::NotificationService::current()->Notify(
    554         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
    555         content::Source<LocationBar>(this),
    556         content::NotificationService::NoDetails());
    557   }
    558 }
    559 
    560 void LocationBarView::UpdateOpenPDFInReaderPrompt() {
    561   open_pdf_in_reader_view_->Update(
    562       model_->GetInputInProgress() ? NULL : GetWebContents());
    563   Layout();
    564   SchedulePaint();
    565 }
    566 
    567 void LocationBarView::UpdateGeneratedCreditCardView() {
    568   generated_credit_card_view_->Update();
    569   Layout();
    570   SchedulePaint();
    571 }
    572 
    573 void LocationBarView::OnFocus() {
    574   // Focus the view widget first which implements accessibility for
    575   // Chrome OS.  It is noop on Win. This should be removed once
    576   // Chrome OS migrates to aura, which uses Views' textfield that receives
    577   // focus. See crbug.com/106428.
    578   NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false);
    579 
    580   // Then focus the native location view which implements accessibility for
    581   // Windows.
    582   location_entry_->SetFocus();
    583 }
    584 
    585 void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction* page_action,
    586                                                   bool preview_enabled) {
    587   if (is_popup_mode_)
    588     return;
    589 
    590   DCHECK(page_action);
    591   WebContents* contents = delegate_->GetWebContents();
    592 
    593   RefreshPageActionViews();
    594   PageActionWithBadgeView* page_action_view =
    595       static_cast<PageActionWithBadgeView*>(GetPageActionView(page_action));
    596   DCHECK(page_action_view);
    597   if (!page_action_view)
    598     return;
    599 
    600   page_action_view->image_view()->set_preview_enabled(preview_enabled);
    601   page_action_view->UpdateVisibility(contents, model_->GetURL());
    602   Layout();
    603   SchedulePaint();
    604 }
    605 
    606 views::View* LocationBarView::GetPageActionView(ExtensionAction *page_action) {
    607   DCHECK(page_action);
    608   for (PageActionViews::const_iterator i(page_action_views_.begin());
    609        i != page_action_views_.end(); ++i) {
    610     if ((*i)->image_view()->page_action() == page_action)
    611       return *i;
    612   }
    613   return NULL;
    614 }
    615 
    616 void LocationBarView::SetStarToggled(bool on) {
    617   if (star_view_)
    618     star_view_->SetToggled(on);
    619 }
    620 
    621 void LocationBarView::ShowBookmarkPrompt() {
    622   if (star_view_ && star_view_->visible())
    623     BookmarkPromptView::ShowPrompt(star_view_, profile_->GetPrefs());
    624 }
    625 
    626 void LocationBarView::ZoomChangedForActiveTab(bool can_show_bubble) {
    627   DCHECK(zoom_view_);
    628   RefreshZoomView();
    629 
    630   Layout();
    631   SchedulePaint();
    632 
    633   if (can_show_bubble && zoom_view_->visible() && delegate_->GetWebContents())
    634     ZoomBubbleView::ShowBubble(delegate_->GetWebContents(), true);
    635 }
    636 
    637 void LocationBarView::RefreshZoomView() {
    638   DCHECK(zoom_view_);
    639   WebContents* web_contents = GetWebContents();
    640   if (!web_contents)
    641     return;
    642 
    643   ZoomController* zoom_controller =
    644       ZoomController::FromWebContents(web_contents);
    645   zoom_view_->Update(zoom_controller);
    646 }
    647 
    648 gfx::Point LocationBarView::GetLocationEntryOrigin() const {
    649   gfx::Point origin(location_entry_view_->bounds().origin());
    650   // If the UI layout is RTL, the coordinate system is not transformed and
    651   // therefore we need to adjust the X coordinate so that bubble appears on the
    652   // right hand side of the location bar.
    653   if (base::i18n::IsRTL())
    654     origin.set_x(width() - origin.x());
    655   views::View::ConvertPointToScreen(this, &origin);
    656   return origin;
    657 }
    658 
    659 void LocationBarView::SetImeInlineAutocompletion(const string16& text) {
    660   ime_inline_autocomplete_view_->SetText(text);
    661   ime_inline_autocomplete_view_->SetVisible(!text.empty());
    662 }
    663 
    664 void LocationBarView::SetGrayTextAutocompletion(const string16& text) {
    665   if (suggested_text_view_->text() != text) {
    666     suggested_text_view_->SetText(text);
    667     suggested_text_view_->SetVisible(!text.empty());
    668     Layout();
    669     SchedulePaint();
    670   }
    671 }
    672 
    673 string16 LocationBarView::GetGrayTextAutocompletion() const {
    674   return HasValidSuggestText() ? suggested_text_view_->text() : string16();
    675 }
    676 
    677 void LocationBarView::SetLocationEntryFocusable(bool focusable) {
    678   OmniboxViewViews* omnibox_views = GetOmniboxViewViews(location_entry_.get());
    679   if (omnibox_views)
    680     omnibox_views->set_focusable(focusable);
    681   else
    682     set_focusable(focusable);
    683 }
    684 
    685 bool LocationBarView::IsLocationEntryFocusableInRootView() const {
    686   OmniboxViewViews* omnibox_views = GetOmniboxViewViews(location_entry_.get());
    687   return omnibox_views ? omnibox_views->IsFocusable() : View::IsFocusable();
    688 }
    689 
    690 gfx::Size LocationBarView::GetPreferredSize() {
    691   return background_border_painter_->GetMinimumSize();
    692 }
    693 
    694 void LocationBarView::Layout() {
    695   if (!location_entry_.get())
    696     return;
    697 
    698   selected_keyword_view_->SetVisible(false);
    699   location_icon_view_->SetVisible(false);
    700   ev_bubble_view_->SetVisible(false);
    701   keyword_hint_view_->SetVisible(false);
    702 
    703   const int item_padding = GetItemPadding();
    704   // The native edit has 1 px of whitespace inside it before the text when the
    705   // text is not scrolled off the leading edge.  The views textfield has 1 px of
    706   // whitespace before the text in the RTL case only.
    707   const int kEditLeadingInternalSpace =
    708       (base::i18n::IsRTL() || GetOmniboxViewWin(location_entry_.get())) ? 1 : 0;
    709   LocationBarLayout leading_decorations(
    710       LocationBarLayout::LEFT_EDGE, item_padding - kEditLeadingInternalSpace);
    711   LocationBarLayout trailing_decorations(LocationBarLayout::RIGHT_EDGE,
    712                                          item_padding);
    713 
    714   const string16 keyword(location_entry_->model()->keyword());
    715   const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
    716   const int bubble_location_y = vertical_edge_thickness() + kBubblePadding;
    717   // In some cases (e.g. fullscreen mode) we may have 0 height.  We still want
    718   // to position our child views in this case, because other things may be
    719   // positioned relative to them (e.g. the "bookmark added" bubble if the user
    720   // hits ctrl-d).
    721   const int location_height = GetInternalHeight(false);
    722   const int bubble_height = std::max(location_height - (kBubblePadding * 2), 0);
    723   if (!keyword.empty() && !is_keyword_hint) {
    724     leading_decorations.AddDecoration(bubble_location_y, bubble_height, true, 0,
    725                                       kBubblePadding, item_padding, 0,
    726                                       selected_keyword_view_);
    727     if (selected_keyword_view_->keyword() != keyword) {
    728       selected_keyword_view_->SetKeyword(keyword);
    729       const TemplateURL* template_url =
    730           TemplateURLServiceFactory::GetForProfile(profile_)->
    731           GetTemplateURLForKeyword(keyword);
    732       if (template_url && template_url->IsExtensionKeyword()) {
    733         gfx::Image image = extensions::OmniboxAPI::Get(profile_)->
    734             GetOmniboxIcon(template_url->GetExtensionId());
    735         selected_keyword_view_->SetImage(image.AsImageSkia());
    736         selected_keyword_view_->set_is_extension_icon(true);
    737       } else {
    738         selected_keyword_view_->SetImage(
    739             *(GetThemeProvider()->GetImageSkiaNamed(IDR_OMNIBOX_SEARCH)));
    740         selected_keyword_view_->set_is_extension_icon(false);
    741       }
    742     }
    743   } else if (model_->GetSecurityLevel(false) == ToolbarModel::EV_SECURE) {
    744     ev_bubble_view_->SetLabel(model_->GetEVCertName());
    745     // The largest fraction of the omnibox that can be taken by the EV bubble.
    746     const double kMaxBubbleFraction = 0.5;
    747     leading_decorations.AddDecoration(bubble_location_y, bubble_height, false,
    748                                       kMaxBubbleFraction, kBubblePadding,
    749                                       item_padding, 0, ev_bubble_view_);
    750   } else {
    751     leading_decorations.AddDecoration(
    752         vertical_edge_thickness(), location_height,
    753         GetBuiltInHorizontalPaddingForChildViews(),
    754         location_icon_view_);
    755   }
    756 
    757   if (star_view_ && star_view_->visible()) {
    758     trailing_decorations.AddDecoration(
    759         vertical_edge_thickness(), location_height,
    760         GetBuiltInHorizontalPaddingForChildViews(), star_view_);
    761   }
    762   if (script_bubble_icon_view_ && script_bubble_icon_view_->visible()) {
    763     trailing_decorations.AddDecoration(
    764         vertical_edge_thickness(), location_height,
    765         GetBuiltInHorizontalPaddingForChildViews(),
    766         script_bubble_icon_view_);
    767   }
    768   if (open_pdf_in_reader_view_ && open_pdf_in_reader_view_->visible()) {
    769     trailing_decorations.AddDecoration(
    770         vertical_edge_thickness(), location_height,
    771         GetBuiltInHorizontalPaddingForChildViews(),
    772         open_pdf_in_reader_view_);
    773   }
    774   for (PageActionViews::const_iterator i(page_action_views_.begin());
    775        i != page_action_views_.end(); ++i) {
    776     if ((*i)->visible()) {
    777       trailing_decorations.AddDecoration(
    778           vertical_edge_thickness(), location_height,
    779           GetBuiltInHorizontalPaddingForChildViews(), (*i));
    780     }
    781   }
    782   if (zoom_view_->visible()) {
    783     trailing_decorations.AddDecoration(vertical_edge_thickness(),
    784                                        location_height, 0, zoom_view_);
    785   }
    786   for (ContentSettingViews::const_reverse_iterator i(
    787            content_setting_views_.rbegin()); i != content_setting_views_.rend();
    788        ++i) {
    789     if ((*i)->visible()) {
    790       trailing_decorations.AddDecoration(
    791           bubble_location_y, bubble_height, false, 0, item_padding,
    792           item_padding, GetBuiltInHorizontalPaddingForChildViews(), (*i));
    793     }
    794   }
    795   if (generated_credit_card_view_->visible()) {
    796     trailing_decorations.AddDecoration(vertical_edge_thickness(),
    797                                        location_height, 0,
    798                                        generated_credit_card_view_);
    799   }
    800   if (mic_search_view_->visible()) {
    801     trailing_decorations.AddDecoration(vertical_edge_thickness(),
    802                                        location_height, 0, mic_search_view_);
    803   }
    804   // Because IMEs may eat the tab key, we don't show "press tab to search" while
    805   // IME composition is in progress.
    806   if (!keyword.empty() && is_keyword_hint &&
    807       !location_entry_->IsImeComposing()) {
    808     trailing_decorations.AddDecoration(vertical_edge_thickness(),
    809                                        location_height, true, 0, item_padding,
    810                                        item_padding, 0, keyword_hint_view_);
    811     if (keyword_hint_view_->keyword() != keyword)
    812       keyword_hint_view_->SetKeyword(keyword);
    813   }
    814 
    815   // Perform layout.
    816   const int horizontal_edge_thickness = GetHorizontalEdgeThickness();
    817   int full_width = width() - 2 * horizontal_edge_thickness;
    818   int entry_width = full_width;
    819   leading_decorations.LayoutPass1(&entry_width);
    820   trailing_decorations.LayoutPass1(&entry_width);
    821   leading_decorations.LayoutPass2(&entry_width);
    822   trailing_decorations.LayoutPass2(&entry_width);
    823 
    824   int location_needed_width = location_entry_->TextWidth();
    825   int available_width = entry_width - location_needed_width;
    826   // The bounds must be wide enough for all the decorations to fit.
    827   gfx::Rect location_bounds(
    828       horizontal_edge_thickness, vertical_edge_thickness(),
    829       std::max(full_width, full_width - entry_width), location_height);
    830   leading_decorations.LayoutPass3(&location_bounds, &available_width);
    831   trailing_decorations.LayoutPass3(&location_bounds, &available_width);
    832 
    833   // Layout out the suggested text view right aligned to the location
    834   // entry. Only show the suggested text if we can fit the text from one
    835   // character before the end of the selection to the end of the text and the
    836   // suggested text. If we can't it means either the suggested text is too big,
    837   // or the user has scrolled.
    838 
    839   // TODO(sky): We could potentially adjust this to take into account suggested
    840   // text to force using minimum size if necessary, but currently the chance of
    841   // showing keyword hints and suggested text is minimal and we're not confident
    842   // this is the right approach for suggested text.
    843 
    844   OmniboxViewViews* omnibox_views =
    845       GetOmniboxViewViews(location_entry_.get());
    846   int omnibox_views_margin = 0;
    847   if (suggested_text_view_->visible()) {
    848     // We do not display the suggested text when it contains a mix of RTL and
    849     // LTR characters since this could mean the suggestion should be displayed
    850     // in the middle of the string.
    851     base::i18n::TextDirection text_direction =
    852         base::i18n::GetStringDirection(location_entry_->GetText());
    853     if (text_direction !=
    854         base::i18n::GetStringDirection(suggested_text_view_->text()))
    855       text_direction = base::i18n::UNKNOWN_DIRECTION;
    856 
    857     // TODO(sky): need to layout when the user changes caret position.
    858     gfx::Size suggested_text_size(suggested_text_view_->GetPreferredSize());
    859     if (suggested_text_size.width() > available_width ||
    860         text_direction == base::i18n::UNKNOWN_DIRECTION) {
    861       // Hide the suggested text if the user has scrolled or we can't fit all
    862       // the suggested text, or we have a mix of RTL and LTR characters.
    863       suggested_text_view_->SetBounds(0, 0, 0, 0);
    864     } else {
    865       location_needed_width =
    866           std::min(location_needed_width,
    867                    location_bounds.width() - suggested_text_size.width());
    868       gfx::Rect suggested_text_bounds(location_bounds.origin(),
    869                                       suggested_text_size);
    870       // TODO(sky): figure out why this needs the -1.
    871       suggested_text_bounds.Offset(location_needed_width - 1, 0);
    872       // For non-views the omnibox needs to be shrunk so that the suggest text
    873       // is visible.
    874       if (!omnibox_views)
    875         location_bounds.set_width(location_needed_width);
    876 
    877       // We reverse the order of the location entry and suggested text if:
    878       // - Chrome is RTL but the text is fully LTR, or
    879       // - Chrome is LTR but the text is fully RTL.
    880       // This ensures the suggested text is correctly displayed to the right
    881       // (or left) of the user text.
    882       if (text_direction == (base::i18n::IsRTL() ?
    883           base::i18n::LEFT_TO_RIGHT : base::i18n::RIGHT_TO_LEFT)) {
    884         // TODO(sky): Figure out why we need the +1.
    885         suggested_text_bounds.set_x(location_bounds.x() + 1);
    886         if (omnibox_views) {
    887           // Use a margin to prevent the omnibox text from overlapping the
    888           // suggest text.
    889           omnibox_views_margin = suggested_text_bounds.width();
    890         } else {
    891           // Non-views doesn't support margins so move the omnibox over.
    892           location_bounds.set_x(
    893               location_bounds.x() + suggested_text_bounds.width());
    894         }
    895       }
    896       suggested_text_view_->SetBoundsRect(suggested_text_bounds);
    897     }
    898   }
    899 
    900   if (omnibox_views)
    901     omnibox_views->SetHorizontalMargins(0, omnibox_views_margin);
    902 
    903   // Layout |ime_inline_autocomplete_view_| next to the user input.
    904   if (ime_inline_autocomplete_view_->visible()) {
    905     int width =
    906         ime_inline_autocomplete_view_->font().GetStringWidth(
    907             ime_inline_autocomplete_view_->text()) +
    908         ime_inline_autocomplete_view_->GetInsets().width();
    909     // All the target languages (IMEs) are LTR, and we do not need to support
    910     // RTL so far.  In other words, no testable RTL environment so far.
    911     int x = location_needed_width;
    912     if (width > entry_width)
    913       x = 0;
    914     else if (location_needed_width + width > entry_width)
    915       x = entry_width - width;
    916     location_bounds.set_width(x);
    917     ime_inline_autocomplete_view_->SetBounds(
    918         location_bounds.right(), location_bounds.y(),
    919         std::min(width, entry_width),
    920         ime_inline_autocomplete_view_->GetPreferredSize().height());
    921   }
    922 
    923   location_entry_view_->SetBoundsRect(location_bounds);
    924 }
    925 
    926 void LocationBarView::OnPaint(gfx::Canvas* canvas) {
    927   View::OnPaint(canvas);
    928 
    929   // Fill the location bar background color behind the border.  Parts of the
    930   // border images are meant to rest atop the toolbar background and parts atop
    931   // the omnibox background, so we can't just blindly fill our entire bounds.
    932   const int horizontal_edge_thickness = GetHorizontalEdgeThickness();
    933   if (!background_filling_painter_) {
    934     gfx::Rect bounds(GetContentsBounds());
    935     bounds.Inset(horizontal_edge_thickness, vertical_edge_thickness());
    936     SkColor color(GetColor(ToolbarModel::NONE, BACKGROUND));
    937     if (is_popup_mode_) {
    938       canvas->FillRect(bounds, color);
    939     } else {
    940       SkPaint paint;
    941       paint.setStyle(SkPaint::kFill_Style);
    942       paint.setColor(color);
    943       const int kBorderCornerRadius = 2;
    944       canvas->DrawRoundRect(bounds, kBorderCornerRadius, paint);
    945     }
    946   }
    947 
    948   // Maximized popup windows don't draw the horizontal edges.  We implement this
    949   // by simply expanding the paint area outside the view by the edge thickness.
    950   gfx::Rect background_rect(GetContentsBounds());
    951   if (is_popup_mode_ && (horizontal_edge_thickness == 0))
    952     background_rect.Inset(-kPopupEdgeThickness, 0);
    953   views::Painter::PaintPainterAt(canvas, background_border_painter_.get(),
    954                                  background_rect);
    955   if (background_filling_painter_)
    956     background_filling_painter_->Paint(canvas, size());
    957 
    958   if (!is_popup_mode_)
    959     PaintPageActionBackgrounds(canvas);
    960 
    961   // For non-InstantExtendedAPI cases, if necessary, show focus rect.
    962   // Note: |Canvas::DrawFocusRect| paints a dashed rect with gray color.
    963   if (show_focus_rect_ && HasFocus()) {
    964     gfx::Rect r = location_entry_view_->bounds();
    965     // TODO(jamescook): Is this still needed?
    966     r.Inset(-1, 0);
    967 #if defined(OS_WIN)
    968     r.Inset(0, -1);
    969 #endif
    970     canvas->DrawFocusRect(r);
    971   }
    972 }
    973 
    974 void LocationBarView::SetShowFocusRect(bool show) {
    975   show_focus_rect_ = show;
    976   SchedulePaint();
    977 }
    978 
    979 void LocationBarView::SelectAll() {
    980   location_entry_->SelectAll(true);
    981 }
    982 
    983 #if defined(OS_WIN) && !defined(USE_AURA)
    984 bool LocationBarView::OnMousePressed(const ui::MouseEvent& event) {
    985   UINT msg;
    986   if (event.IsLeftMouseButton()) {
    987     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
    988         WM_LBUTTONDBLCLK : WM_LBUTTONDOWN;
    989   } else if (event.IsMiddleMouseButton()) {
    990     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
    991         WM_MBUTTONDBLCLK : WM_MBUTTONDOWN;
    992   } else if (event.IsRightMouseButton()) {
    993     msg = (event.flags() & ui::EF_IS_DOUBLE_CLICK) ?
    994         WM_RBUTTONDBLCLK : WM_RBUTTONDOWN;
    995   } else {
    996     NOTREACHED();
    997     return false;
    998   }
    999   OnMouseEvent(event, msg);
   1000   return true;
   1001 }
   1002 
   1003 bool LocationBarView::OnMouseDragged(const ui::MouseEvent& event) {
   1004   OnMouseEvent(event, WM_MOUSEMOVE);
   1005   return true;
   1006 }
   1007 
   1008 void LocationBarView::OnMouseReleased(const ui::MouseEvent& event) {
   1009   UINT msg;
   1010   if (event.IsLeftMouseButton()) {
   1011     msg = WM_LBUTTONUP;
   1012   } else if (event.IsMiddleMouseButton()) {
   1013     msg = WM_MBUTTONUP;
   1014   } else if (event.IsRightMouseButton()) {
   1015     msg = WM_RBUTTONUP;
   1016   } else {
   1017     NOTREACHED();
   1018     return;
   1019   }
   1020   OnMouseEvent(event, msg);
   1021 }
   1022 
   1023 void LocationBarView::OnMouseCaptureLost() {
   1024   OmniboxViewWin* omnibox_win = GetOmniboxViewWin(location_entry_.get());
   1025   if (omnibox_win)
   1026     omnibox_win->HandleExternalMsg(WM_CAPTURECHANGED, 0, CPoint());
   1027 }
   1028 #endif
   1029 
   1030 views::View* LocationBarView::generated_credit_card_view() {
   1031   return generated_credit_card_view_;
   1032 }
   1033 
   1034 void LocationBarView::OnAutocompleteAccept(
   1035     const GURL& url,
   1036     WindowOpenDisposition disposition,
   1037     content::PageTransition transition,
   1038     const GURL& alternate_nav_url) {
   1039   // WARNING: don't add an early return here. The calls after the if must
   1040   // happen.
   1041   if (url.is_valid()) {
   1042     location_input_ = UTF8ToUTF16(url.spec());
   1043     disposition_ = disposition;
   1044     transition_ = content::PageTransitionFromInt(
   1045         transition | content::PAGE_TRANSITION_FROM_ADDRESS_BAR);
   1046 
   1047     if (command_updater_) {
   1048       if (!alternate_nav_url.is_valid()) {
   1049         command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
   1050       } else {
   1051         AlternateNavURLFetcher* fetcher =
   1052             new AlternateNavURLFetcher(alternate_nav_url);
   1053         // The AlternateNavURLFetcher will listen for the pending navigation
   1054         // notification that will be issued as a result of the "open URL." It
   1055         // will automatically install itself into that navigation controller.
   1056         command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
   1057         if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
   1058           // I'm not sure this should be reachable, but I'm not also sure enough
   1059           // that it shouldn't to stick in a NOTREACHED().  In any case, this is
   1060           // harmless.
   1061           delete fetcher;
   1062         } else {
   1063           // The navigation controller will delete the fetcher.
   1064         }
   1065       }
   1066     }
   1067   }
   1068 }
   1069 
   1070 void LocationBarView::OnChanged() {
   1071   location_icon_view_->SetImage(
   1072       GetThemeProvider()->GetImageSkiaNamed(location_entry_->GetIcon()));
   1073   location_icon_view_->ShowTooltip(!GetLocationEntry()->IsEditingOrEmpty());
   1074 
   1075   Layout();
   1076   SchedulePaint();
   1077 }
   1078 
   1079 void LocationBarView::OnSelectionBoundsChanged() {
   1080 }
   1081 
   1082 void LocationBarView::OnInputInProgress(bool in_progress) {
   1083   delegate_->OnInputInProgress(in_progress);
   1084 }
   1085 
   1086 void LocationBarView::OnKillFocus() {
   1087 }
   1088 
   1089 void LocationBarView::OnSetFocus() {
   1090   views::FocusManager* focus_manager = GetFocusManager();
   1091   if (!focus_manager) {
   1092     NOTREACHED();
   1093     return;
   1094   }
   1095   focus_manager->SetFocusedView(this);
   1096 }
   1097 
   1098 gfx::Image LocationBarView::GetFavicon() const {
   1099   return FaviconTabHelper::FromWebContents(
   1100       delegate_->GetWebContents())->GetFavicon();
   1101 }
   1102 
   1103 string16 LocationBarView::GetTitle() const {
   1104   return delegate_->GetWebContents()->GetTitle();
   1105 }
   1106 
   1107 InstantController* LocationBarView::GetInstant() {
   1108   return delegate_->GetInstant();
   1109 }
   1110 
   1111 WebContents* LocationBarView::GetWebContents() const {
   1112   return delegate_->GetWebContents();
   1113 }
   1114 
   1115 // static
   1116 int LocationBarView::GetBuiltInHorizontalPaddingForChildViews() {
   1117   return (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) ?
   1118       GetItemPadding() / 2 : 0;
   1119 }
   1120 
   1121 int LocationBarView::GetHorizontalEdgeThickness() const {
   1122   // In maximized popup mode, there isn't any edge.
   1123   return (is_popup_mode_ && browser_ && browser_->window() &&
   1124       browser_->window()->IsMaximized()) ? 0 : vertical_edge_thickness();
   1125 }
   1126 
   1127 void LocationBarView::RefreshContentSettingViews() {
   1128   for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
   1129        i != content_setting_views_.end(); ++i) {
   1130     (*i)->Update(model_->GetInputInProgress() ? NULL : GetWebContents());
   1131   }
   1132 }
   1133 
   1134 void LocationBarView::DeletePageActionViews() {
   1135   for (PageActionViews::const_iterator i(page_action_views_.begin());
   1136        i != page_action_views_.end(); ++i)
   1137     RemoveChildView(*i);
   1138   STLDeleteElements(&page_action_views_);
   1139 }
   1140 
   1141 void LocationBarView::RefreshPageActionViews() {
   1142   if (is_popup_mode_)
   1143     return;
   1144 
   1145   // Remember the previous visibility of the page actions so that we can
   1146   // notify when this changes.
   1147   std::map<ExtensionAction*, bool> old_visibility;
   1148   for (PageActionViews::const_iterator i(page_action_views_.begin());
   1149        i != page_action_views_.end(); ++i) {
   1150     old_visibility[(*i)->image_view()->page_action()] = (*i)->visible();
   1151   }
   1152 
   1153   std::vector<ExtensionAction*> new_page_actions;
   1154 
   1155   WebContents* contents = delegate_->GetWebContents();
   1156   if (contents) {
   1157     extensions::TabHelper* extensions_tab_helper =
   1158         extensions::TabHelper::FromWebContents(contents);
   1159     extensions::LocationBarController* controller =
   1160         extensions_tab_helper->location_bar_controller();
   1161     new_page_actions = controller->GetCurrentActions();
   1162   }
   1163 
   1164   // On startup we sometimes haven't loaded any extensions. This makes sure
   1165   // we catch up when the extensions (and any page actions) load.
   1166   if (page_actions_ != new_page_actions) {
   1167     page_actions_.swap(new_page_actions);
   1168     DeletePageActionViews();  // Delete the old views (if any).
   1169 
   1170     page_action_views_.resize(page_actions_.size());
   1171     View* right_anchor = open_pdf_in_reader_view_;
   1172     if (!right_anchor)
   1173       right_anchor = star_view_;
   1174     if (!right_anchor)
   1175       right_anchor = script_bubble_icon_view_;
   1176     DCHECK(right_anchor);
   1177 
   1178     // Add the page actions in reverse order, so that the child views are
   1179     // inserted in left-to-right order for accessibility.
   1180     for (int i = page_actions_.size() - 1; i >= 0; --i) {
   1181       page_action_views_[i] = new PageActionWithBadgeView(
   1182           delegate_->CreatePageActionImageView(this, page_actions_[i]));
   1183       page_action_views_[i]->SetVisible(false);
   1184       AddChildViewAt(page_action_views_[i], GetIndexOf(right_anchor));
   1185     }
   1186   }
   1187 
   1188   if (!page_action_views_.empty() && contents) {
   1189     Browser* browser = chrome::FindBrowserWithWebContents(contents);
   1190     GURL url = browser->tab_strip_model()->GetActiveWebContents()->GetURL();
   1191 
   1192     for (PageActionViews::const_iterator i(page_action_views_.begin());
   1193          i != page_action_views_.end(); ++i) {
   1194       (*i)->UpdateVisibility(model_->GetInputInProgress() ? NULL : contents,
   1195                              url);
   1196 
   1197       // Check if the visibility of the action changed and notify if it did.
   1198       ExtensionAction* action = (*i)->image_view()->page_action();
   1199       if (old_visibility.find(action) == old_visibility.end() ||
   1200           old_visibility[action] != (*i)->visible()) {
   1201         content::NotificationService::current()->Notify(
   1202             chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
   1203             content::Source<ExtensionAction>(action),
   1204             content::Details<WebContents>(contents));
   1205       }
   1206     }
   1207   }
   1208 }
   1209 
   1210 size_t LocationBarView::ScriptBubbleScriptsRunning() {
   1211   WebContents* contents = delegate_->GetWebContents();
   1212   if (!contents)
   1213     return false;
   1214   extensions::TabHelper* extensions_tab_helper =
   1215       extensions::TabHelper::FromWebContents(contents);
   1216   if (!extensions_tab_helper)
   1217     return false;
   1218   extensions::ScriptBubbleController* script_bubble_controller =
   1219       extensions_tab_helper->script_bubble_controller();
   1220   if (!script_bubble_controller)
   1221     return false;
   1222   size_t script_count =
   1223       script_bubble_controller->extensions_running_scripts().size();
   1224   return script_count;
   1225 }
   1226 
   1227 void LocationBarView::RefreshScriptBubble() {
   1228   if (!script_bubble_icon_view_)
   1229     return;
   1230   size_t script_count = ScriptBubbleScriptsRunning();
   1231   script_bubble_icon_view_->SetVisible(script_count > 0);
   1232   if (script_count > 0)
   1233     script_bubble_icon_view_->SetScriptCount(script_count);
   1234 }
   1235 
   1236 #if defined(OS_WIN) && !defined(USE_AURA)
   1237 void LocationBarView::OnMouseEvent(const ui::MouseEvent& event, UINT msg) {
   1238   OmniboxViewWin* omnibox_win = GetOmniboxViewWin(location_entry_.get());
   1239   if (omnibox_win) {
   1240     UINT flags = event.native_event().wParam;
   1241     gfx::Point screen_point(event.location());
   1242     ConvertPointToScreen(this, &screen_point);
   1243     omnibox_win->HandleExternalMsg(msg, flags, screen_point.ToPOINT());
   1244   }
   1245 }
   1246 #endif
   1247 
   1248 void LocationBarView::ShowFirstRunBubbleInternal() {
   1249 #if !defined(OS_CHROMEOS)
   1250   // First run bubble doesn't make sense for Chrome OS.
   1251   Browser* browser = GetBrowserFromDelegate(delegate_);
   1252   if (!browser)
   1253     return; // Possible when browser is shutting down.
   1254 
   1255   FirstRunBubble::ShowBubble(browser, location_icon_view_);
   1256 #endif
   1257 }
   1258 
   1259 void LocationBarView::PaintPageActionBackgrounds(gfx::Canvas* canvas) {
   1260   WebContents* web_contents = GetWebContents();
   1261   // web_contents may be NULL while the browser is shutting down.
   1262   if (!web_contents)
   1263     return;
   1264 
   1265   const int32 tab_id = SessionID::IdForTab(web_contents);
   1266   const ToolbarModel::SecurityLevel security_level =
   1267       model_->GetSecurityLevel(false);
   1268   const SkColor text_color = GetColor(security_level, TEXT);
   1269   const SkColor background_color = GetColor(security_level, BACKGROUND);
   1270 
   1271   for (PageActionViews::const_iterator
   1272            page_action_view = page_action_views_.begin();
   1273        page_action_view != page_action_views_.end();
   1274        ++page_action_view) {
   1275     gfx::Rect bounds = (*page_action_view)->bounds();
   1276     int horizontal_padding =
   1277         GetItemPadding() - GetBuiltInHorizontalPaddingForChildViews();
   1278     // Make the bounding rectangle include the whole vertical range of the
   1279     // location bar, and the mid-point pixels between adjacent page actions.
   1280     //
   1281     // For odd horizontal_paddings, "horizontal_padding + 1" includes the
   1282     // mid-point between two page actions in the bounding rectangle.  For even
   1283     // paddings, the +1 is dropped, which is right since there is no pixel at
   1284     // the mid-point.
   1285     bounds.Inset(-(horizontal_padding + 1) / 2, 0);
   1286     location_bar_util::PaintExtensionActionBackground(
   1287         *(*page_action_view)->image_view()->page_action(),
   1288         tab_id, canvas, bounds, text_color, background_color);
   1289   }
   1290 }
   1291 
   1292 const char* LocationBarView::GetClassName() const {
   1293   return kViewClassName;
   1294 }
   1295 
   1296 bool LocationBarView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
   1297 #if defined(OS_WIN)
   1298   if (views::FocusManager::IsTabTraversalKeyEvent(event)) {
   1299     if (location_entry_->model()->popup_model()->IsOpen()) {
   1300       // Return true so that the edit sees the tab and moves the selection.
   1301       return true;
   1302     }
   1303     if (keyword_hint_view_->visible() && !event.IsShiftDown()) {
   1304       // Return true so the edit gets the tab event and enters keyword mode.
   1305       return true;
   1306     }
   1307   }
   1308 
   1309 #if defined(USE_AURA)
   1310   NOTIMPLEMENTED();
   1311 #else
   1312   OmniboxViewWin* omnibox_win = GetOmniboxViewWin(location_entry_.get());
   1313   if (omnibox_win)
   1314     return omnibox_win->SkipDefaultKeyEventProcessing(event);
   1315 #endif  // USE_AURA
   1316 #endif  // OS_WIN
   1317 
   1318   // This method is not used for Linux ports. See FocusManager::OnKeyEvent() in
   1319   // src/ui/views/focus/focus_manager.cc for details.
   1320   return false;
   1321 }
   1322 
   1323 void LocationBarView::GetAccessibleState(ui::AccessibleViewState* state) {
   1324   if (!location_entry_)
   1325     return;
   1326 
   1327   state->role = ui::AccessibilityTypes::ROLE_LOCATION_BAR;
   1328   state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
   1329   state->value = location_entry_->GetText();
   1330 
   1331   string16::size_type entry_start;
   1332   string16::size_type entry_end;
   1333   location_entry_->GetSelectionBounds(&entry_start, &entry_end);
   1334   state->selection_start = entry_start;
   1335   state->selection_end = entry_end;
   1336 
   1337   if (is_popup_mode_) {
   1338     state->state |= ui::AccessibilityTypes::STATE_READONLY;
   1339   } else {
   1340     state->set_value_callback =
   1341         base::Bind(&LocationBarView::AccessibilitySetValue,
   1342                    weak_ptr_factory_.GetWeakPtr());
   1343   }
   1344 }
   1345 
   1346 bool LocationBarView::HasFocus() const {
   1347   return location_entry_->model()->has_focus();
   1348 }
   1349 
   1350 void LocationBarView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   1351   if (browser_ && browser_->instant_controller() && parent())
   1352     browser_->instant_controller()->SetOmniboxBounds(bounds());
   1353   OmniboxPopupView* popup = location_entry_->model()->popup_model()->view();
   1354   if (popup->IsOpen())
   1355     popup->UpdatePopupAppearance();
   1356 }
   1357 
   1358 void LocationBarView::ButtonPressed(views::Button* sender,
   1359                                     const ui::Event& event) {
   1360   DCHECK_EQ(mic_search_view_, sender);
   1361   command_updater_->ExecuteCommand(IDC_TOGGLE_SPEECH_INPUT);
   1362 }
   1363 
   1364 void LocationBarView::WriteDragDataForView(views::View* sender,
   1365                                            const gfx::Point& press_pt,
   1366                                            OSExchangeData* data) {
   1367   DCHECK_NE(GetDragOperationsForView(sender, press_pt),
   1368             ui::DragDropTypes::DRAG_NONE);
   1369 
   1370   WebContents* web_contents = GetWebContents();
   1371   FaviconTabHelper* favicon_tab_helper =
   1372       FaviconTabHelper::FromWebContents(web_contents);
   1373   gfx::ImageSkia favicon = favicon_tab_helper->GetFavicon().AsImageSkia();
   1374   button_drag_utils::SetURLAndDragImage(web_contents->GetURL(),
   1375                                         web_contents->GetTitle(),
   1376                                         favicon,
   1377                                         data,
   1378                                         sender->GetWidget());
   1379 }
   1380 
   1381 int LocationBarView::GetDragOperationsForView(views::View* sender,
   1382                                               const gfx::Point& p) {
   1383   DCHECK((sender == location_icon_view_) || (sender == ev_bubble_view_));
   1384   WebContents* web_contents = delegate_->GetWebContents();
   1385   return (web_contents && web_contents->GetURL().is_valid() &&
   1386           !GetLocationEntry()->IsEditingOrEmpty()) ?
   1387       (ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK) :
   1388       ui::DragDropTypes::DRAG_NONE;
   1389 }
   1390 
   1391 bool LocationBarView::CanStartDragForView(View* sender,
   1392                                           const gfx::Point& press_pt,
   1393                                           const gfx::Point& p) {
   1394   return true;
   1395 }
   1396 
   1397 ////////////////////////////////////////////////////////////////////////////////
   1398 // LocationBarView, LocationBar implementation:
   1399 
   1400 void LocationBarView::ShowFirstRunBubble() {
   1401   // Wait until search engines have loaded to show the first run bubble.
   1402   TemplateURLService* url_service =
   1403       TemplateURLServiceFactory::GetForProfile(profile_);
   1404   if (!url_service->loaded()) {
   1405     template_url_service_ = url_service;
   1406     template_url_service_->AddObserver(this);
   1407     template_url_service_->Load();
   1408     return;
   1409   }
   1410   ShowFirstRunBubbleInternal();
   1411 }
   1412 
   1413 string16 LocationBarView::GetInputString() const {
   1414   return location_input_;
   1415 }
   1416 
   1417 WindowOpenDisposition LocationBarView::GetWindowOpenDisposition() const {
   1418   return disposition_;
   1419 }
   1420 
   1421 content::PageTransition LocationBarView::GetPageTransition() const {
   1422   return transition_;
   1423 }
   1424 
   1425 void LocationBarView::AcceptInput() {
   1426   location_entry_->model()->AcceptInput(CURRENT_TAB, false);
   1427 }
   1428 
   1429 void LocationBarView::FocusLocation(bool select_all) {
   1430   location_entry_->SetFocus();
   1431   if (select_all)
   1432     location_entry_->SelectAll(true);
   1433 }
   1434 
   1435 void LocationBarView::FocusSearch() {
   1436   location_entry_->SetFocus();
   1437   location_entry_->SetForcedQuery();
   1438 }
   1439 
   1440 void LocationBarView::SaveStateToContents(WebContents* contents) {
   1441   location_entry_->SaveStateToTab(contents);
   1442 }
   1443 
   1444 void LocationBarView::Revert() {
   1445   location_entry_->RevertAll();
   1446 }
   1447 
   1448 const OmniboxView* LocationBarView::GetLocationEntry() const {
   1449   return location_entry_.get();
   1450 }
   1451 
   1452 OmniboxView* LocationBarView::GetLocationEntry() {
   1453   return location_entry_.get();
   1454 }
   1455 
   1456 LocationBarTesting* LocationBarView::GetLocationBarForTesting() {
   1457   return this;
   1458 }
   1459 
   1460 int LocationBarView::PageActionCount() {
   1461   return page_action_views_.size();
   1462 }
   1463 
   1464 int LocationBarView::PageActionVisibleCount() {
   1465   int result = 0;
   1466   for (size_t i = 0; i < page_action_views_.size(); i++) {
   1467     if (page_action_views_[i]->visible())
   1468       ++result;
   1469   }
   1470   return result;
   1471 }
   1472 
   1473 ExtensionAction* LocationBarView::GetPageAction(size_t index) {
   1474   if (index < page_action_views_.size())
   1475     return page_action_views_[index]->image_view()->page_action();
   1476 
   1477   NOTREACHED();
   1478   return NULL;
   1479 }
   1480 
   1481 ExtensionAction* LocationBarView::GetVisiblePageAction(size_t index) {
   1482   size_t current = 0;
   1483   for (size_t i = 0; i < page_action_views_.size(); ++i) {
   1484     if (page_action_views_[i]->visible()) {
   1485       if (current == index)
   1486         return page_action_views_[i]->image_view()->page_action();
   1487 
   1488       ++current;
   1489     }
   1490   }
   1491 
   1492   NOTREACHED();
   1493   return NULL;
   1494 }
   1495 
   1496 void LocationBarView::TestPageActionPressed(size_t index) {
   1497   size_t current = 0;
   1498   for (size_t i = 0; i < page_action_views_.size(); ++i) {
   1499     if (page_action_views_[i]->visible()) {
   1500       if (current == index) {
   1501         page_action_views_[i]->image_view()->ExecuteAction(
   1502             ExtensionPopup::SHOW);
   1503         return;
   1504       }
   1505       ++current;
   1506     }
   1507   }
   1508 
   1509   NOTREACHED();
   1510 }
   1511 
   1512 bool LocationBarView::GetBookmarkStarVisibility() {
   1513   DCHECK(star_view_);
   1514   return star_view_->visible();
   1515 }
   1516 
   1517 void LocationBarView::OnTemplateURLServiceChanged() {
   1518   template_url_service_->RemoveObserver(this);
   1519   template_url_service_ = NULL;
   1520   // If the browser is no longer active, let's not show the info bubble, as this
   1521   // would make the browser the active window again.
   1522   if (location_entry_view_ && location_entry_view_->GetWidget()->IsActive())
   1523     ShowFirstRunBubble();
   1524 }
   1525 
   1526 void LocationBarView::Observe(int type,
   1527                               const content::NotificationSource& source,
   1528                               const content::NotificationDetails& details) {
   1529   switch (type) {
   1530     case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED: {
   1531       // Only update if the updated action box was for the active tab contents.
   1532       WebContents* target_tab = content::Details<WebContents>(details).ptr();
   1533       if (target_tab == GetWebContents())
   1534         UpdatePageActions();
   1535       break;
   1536     }
   1537 
   1538     default:
   1539       NOTREACHED() << "Unexpected notification.";
   1540   }
   1541 }
   1542 
   1543 void LocationBarView::ModelChanged(const SearchModel::State& old_state,
   1544                                    const SearchModel::State& new_state) {
   1545   const bool visible =
   1546       !model_->GetInputInProgress() && new_state.voice_search_supported;
   1547   if (mic_search_view_->visible() != visible) {
   1548     mic_search_view_->SetVisible(visible);
   1549     Layout();
   1550   }
   1551 }
   1552 
   1553 int LocationBarView::GetInternalHeight(bool use_preferred_size) {
   1554   int total_height =
   1555       use_preferred_size ? GetPreferredSize().height() : height();
   1556   return std::max(total_height - (vertical_edge_thickness() * 2), 0);
   1557 }
   1558 
   1559 bool LocationBarView::HasValidSuggestText() const {
   1560   return suggested_text_view_->visible() &&
   1561       !suggested_text_view_->size().IsEmpty();
   1562 }
   1563 
   1564 void LocationBarView::AccessibilitySetValue(const string16& new_value) {
   1565   location_entry_->SetUserText(new_value);
   1566 }
   1567