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.
5 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
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/extension_service.h"
21 #include "chrome/browser/extensions/location_bar_controller.h"
22 #include "chrome/browser/extensions/tab_helper.h"
23 #include "chrome/browser/favicon/favicon_tab_helper.h"
24 #include "chrome/browser/search/instant_service.h"
25 #include "chrome/browser/search/instant_service_factory.h"
26 #include "chrome/browser/search/search.h"
27 #include "chrome/browser/search_engines/template_url.h"
28 #include "chrome/browser/search_engines/template_url_service.h"
29 #include "chrome/browser/search_engines/template_url_service_factory.h"
30 #include "chrome/browser/translate/translate_service.h"
31 #include "chrome/browser/translate/translate_tab_helper.h"
32 #include "chrome/browser/ui/browser.h"
33 #include "chrome/browser/ui/browser_finder.h"
34 #include "chrome/browser/ui/browser_instant_controller.h"
35 #include "chrome/browser/ui/browser_window.h"
36 #include "chrome/browser/ui/omnibox/location_bar_util.h"
37 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
38 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
39 #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h"
40 #include "chrome/browser/ui/tabs/tab_strip_model.h"
41 #include "chrome/browser/ui/view_ids.h"
42 #include "chrome/browser/ui/views/bookmarks/bookmark_prompt_view.h"
43 #include "chrome/browser/ui/views/browser_dialogs.h"
44 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
45 #include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
46 #include "chrome/browser/ui/views/location_bar/generated_credit_card_view.h"
47 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
48 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
49 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
50 #include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
51 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
52 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
53 #include "chrome/browser/ui/views/location_bar/selected_keyword_view.h"
54 #include "chrome/browser/ui/views/location_bar/star_view.h"
55 #include "chrome/browser/ui/views/location_bar/translate_icon_view.h"
56 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
57 #include "chrome/browser/ui/views/location_bar/zoom_view.h"
58 #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
59 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
60 #include "chrome/browser/ui/views/toolbar/origin_chip_view.h"
61 #include "chrome/browser/ui/zoom/zoom_controller.h"
62 #include "chrome/common/chrome_switches.h"
63 #include "chrome/common/pref_names.h"
64 #include "content/public/browser/notification_service.h"
65 #include "content/public/browser/render_widget_host_view.h"
66 #include "content/public/browser/web_contents.h"
67 #include "extensions/browser/extension_system.h"
68 #include "extensions/common/feature_switch.h"
69 #include "extensions/common/permissions/permissions_data.h"
70 #include "grit/generated_resources.h"
71 #include "grit/theme_resources.h"
72 #include "ui/base/accessibility/accessible_view_state.h"
73 #include "ui/base/dragdrop/drag_drop_types.h"
74 #include "ui/base/l10n/l10n_util.h"
75 #include "ui/base/layout.h"
76 #include "ui/base/resource/resource_bundle.h"
77 #include "ui/base/theme_provider.h"
78 #include "ui/events/event.h"
79 #include "ui/gfx/canvas.h"
80 #include "ui/gfx/color_utils.h"
81 #include "ui/gfx/image/image.h"
82 #include "ui/gfx/image/image_skia_operations.h"
83 #include "ui/gfx/skia_util.h"
84 #include "ui/gfx/text_utils.h"
85 #include "ui/native_theme/native_theme.h"
86 #include "ui/views/background.h"
87 #include "ui/views/border.h"
88 #include "ui/views/button_drag_utils.h"
89 #include "ui/views/controls/button/image_button.h"
90 #include "ui/views/controls/button/label_button.h"
91 #include "ui/views/controls/button/label_button_border.h"
92 #include "ui/views/controls/label.h"
93 #include "ui/views/widget/widget.h"
95 #if !defined(OS_CHROMEOS)
96 #include "chrome/browser/ui/views/first_run_bubble.h"
99 using content::WebContents
;
104 #if !defined(OS_CHROMEOS)
105 Browser
* GetBrowserFromDelegate(LocationBarView::Delegate
* delegate
) {
106 WebContents
* contents
= delegate
->GetWebContents();
107 return contents
? chrome::FindBrowserWithWebContents(contents
) : NULL
;
111 // Given a containing |height| and a |base_font_list|, shrinks the font size
112 // until the font list will fit within |height| while having its cap height
113 // vertically centered. Returns the correctly-sized font list.
115 // The expected layout:
116 // +--------+-----------------------------------------------+------------+
117 // | | y offset | space |
118 // | +--------+-------------------+------------------+ above |
119 // | | | | internal leading | cap height |
120 // | box | font | ascent (baseline) +------------------+------------+
121 // | height | height | | cap height |
122 // | | |-------------------+------------------+------------+
123 // | | | descent (height - baseline) | space |
124 // | +--------+--------------------------------------+ below |
125 // | | space at bottom | cap height |
126 // +--------+-----------------------------------------------+------------+
128 // center of box height == center of cap height
129 // (i.e. space above cap height == space below cap height)
132 // space at bottom >= 0
133 // (i.e. Entire font must be visible inside the box.)
134 gfx::FontList
GetLargestFontListWithHeightBound(
135 const gfx::FontList
& base_font_list
,
137 gfx::FontList font_list
= base_font_list
;
138 for (int font_size
= font_list
.GetFontSize(); font_size
> 1; --font_size
) {
139 const int internal_leading
=
140 font_list
.GetBaseline() - font_list
.GetCapHeight();
141 // Some platforms don't support getting the cap height, and simply return
142 // the entire font ascent from GetCapHeight(). Centering the ascent makes
143 // the font look too low, so if GetCapHeight() returns the ascent, center
144 // the entire font height instead.
146 height
- ((internal_leading
!= 0) ?
147 font_list
.GetCapHeight() : font_list
.GetHeight());
148 const int y_offset
= space
/ 2 - internal_leading
;
149 const int space_at_bottom
= height
- (y_offset
+ font_list
.GetHeight());
150 if ((y_offset
>= 0) && (space_at_bottom
>= 0))
152 font_list
= font_list
.DeriveWithSizeDelta(-1);
157 // Functor for moving BookmarkManagerPrivate page actions to the right via
159 class IsPageActionViewRightAligned
{
161 explicit IsPageActionViewRightAligned(ExtensionService
* extension_service
)
162 : extension_service_(extension_service
) {}
164 bool operator()(PageActionWithBadgeView
* page_action_view
) {
165 return extensions::PermissionsData::HasAPIPermission(
166 extension_service_
->GetExtensionById(
167 page_action_view
->image_view()->page_action()->extension_id(),
169 extensions::APIPermission::kBookmarkManagerPrivate
);
173 ExtensionService
* extension_service_
;
175 // NOTE: Can't DISALLOW_COPY_AND_ASSIGN as we pass this object by value to
176 // std::stable_partition().
182 // LocationBarView -----------------------------------------------------------
185 const int LocationBarView::kNormalEdgeThickness
= 2;
186 const int LocationBarView::kPopupEdgeThickness
= 1;
187 const int LocationBarView::kIconInternalPadding
= 2;
188 const int LocationBarView::kBubblePadding
= 1;
189 const char LocationBarView::kViewClassName
[] = "LocationBarView";
191 LocationBarView::LocationBarView(Browser
* browser
,
193 CommandUpdater
* command_updater
,
196 : LocationBar(profile
),
197 OmniboxEditController(command_updater
),
201 location_icon_view_(NULL
),
202 ev_bubble_view_(NULL
),
203 ime_inline_autocomplete_view_(NULL
),
204 selected_keyword_view_(NULL
),
205 suggested_text_view_(NULL
),
206 keyword_hint_view_(NULL
),
207 mic_search_view_(NULL
),
209 generated_credit_card_view_(NULL
),
210 open_pdf_in_reader_view_(NULL
),
211 manage_passwords_icon_view_(NULL
),
212 origin_chip_view_(NULL
),
213 translate_icon_view_(NULL
),
215 search_button_(NULL
),
216 is_popup_mode_(is_popup_mode
),
217 show_focus_rect_(false),
218 template_url_service_(NULL
),
219 animation_offset_(0),
220 weak_ptr_factory_(this) {
221 edit_bookmarks_enabled_
.Init(
222 prefs::kEditBookmarksEnabled
, profile
->GetPrefs(),
223 base::Bind(&LocationBarView::Update
, base::Unretained(this),
224 static_cast<content::WebContents
*>(NULL
)));
227 browser_
->search_model()->AddObserver(this);
230 LocationBarView::~LocationBarView() {
231 if (template_url_service_
)
232 template_url_service_
->RemoveObserver(this);
234 browser_
->search_model()->RemoveObserver(this);
238 void LocationBarView::InitTouchableLocationBarChildView(views::View
* view
) {
239 int horizontal_padding
= GetBuiltInHorizontalPaddingForChildViews();
240 if (horizontal_padding
!= 0) {
241 view
->SetBorder(views::Border::CreateEmptyBorder(
242 3, horizontal_padding
, 3, horizontal_padding
));
246 void LocationBarView::Init() {
247 // We need to be in a Widget, otherwise GetNativeTheme() may change and we're
248 // not prepared for that.
251 const int kOmniboxPopupBorderImages
[] =
252 IMAGE_GRID(IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW
);
253 const int kOmniboxBorderImages
[] =
254 IMAGE_GRID(IDR_OMNIBOX_BORDER_AND_SHADOW
);
255 border_painter_
.reset(views::Painter::CreateImageGridPainter(
256 is_popup_mode_
? kOmniboxPopupBorderImages
: kOmniboxBorderImages
));
258 location_icon_view_
= new LocationIconView(this);
259 location_icon_view_
->set_drag_controller(this);
260 AddChildView(location_icon_view_
);
262 // Determine the main font.
263 gfx::FontList font_list
= ResourceBundle::GetSharedInstance().GetFontList(
264 ResourceBundle::BaseFont
);
265 const int current_font_size
= font_list
.GetFontSize();
266 const int desired_font_size
= browser_defaults::kOmniboxFontPixelSize
;
267 if (current_font_size
!= desired_font_size
) {
269 font_list
.DeriveWithSizeDelta(desired_font_size
- current_font_size
);
271 // Shrink large fonts to make them fit.
272 // TODO(pkasting): Stretch the location bar instead in this case.
273 const int location_height
= GetInternalHeight(true);
274 font_list
= GetLargestFontListWithHeightBound(font_list
, location_height
);
276 // Determine the font for use inside the bubbles. The bubble background
277 // images have 1 px thick edges, which we don't want to overlap.
278 const int kBubbleInteriorVerticalPadding
= 1;
279 const int bubble_vertical_padding
=
280 (kBubblePadding
+ kBubbleInteriorVerticalPadding
) * 2;
281 const gfx::FontList
bubble_font_list(
282 GetLargestFontListWithHeightBound(
283 font_list
, location_height
- bubble_vertical_padding
));
285 const SkColor background_color
=
286 GetColor(ToolbarModel::NONE
, LocationBarView::BACKGROUND
);
287 ev_bubble_view_
= new EVBubbleView(
288 bubble_font_list
, GetColor(ToolbarModel::EV_SECURE
, SECURITY_TEXT
),
289 background_color
, this);
290 ev_bubble_view_
->set_drag_controller(this);
291 AddChildView(ev_bubble_view_
);
293 // Initialize the Omnibox view.
294 omnibox_view_
= new OmniboxViewViews(
295 this, profile(), command_updater(),
297 (browser_
->is_app() && CommandLine::ForCurrentProcess()->
298 HasSwitch(switches::kEnableStreamlinedHostedApps
)),
300 omnibox_view_
->Init();
301 omnibox_view_
->SetFocusable(true);
302 AddChildView(omnibox_view_
);
304 // Initialize the inline autocomplete view which is visible only when IME is
305 // turned on. Use the same font with the omnibox and highlighted background.
306 ime_inline_autocomplete_view_
= new views::Label(base::string16(), font_list
);
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_
);
318 const SkColor text_color
= GetColor(ToolbarModel::NONE
, TEXT
);
319 selected_keyword_view_
= new SelectedKeywordView(
320 bubble_font_list
, text_color
, background_color
, profile());
321 AddChildView(selected_keyword_view_
);
323 suggested_text_view_
= new views::Label(base::string16(), font_list
);
324 suggested_text_view_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
325 suggested_text_view_
->SetAutoColorReadabilityEnabled(false);
326 suggested_text_view_
->SetEnabledColor(GetColor(
327 ToolbarModel::NONE
, LocationBarView::DEEMPHASIZED_TEXT
));
328 suggested_text_view_
->SetVisible(false);
329 AddChildView(suggested_text_view_
);
331 keyword_hint_view_
= new KeywordHintView(
332 profile(), font_list
,
333 GetColor(ToolbarModel::NONE
, LocationBarView::DEEMPHASIZED_TEXT
),
335 AddChildView(keyword_hint_view_
);
337 mic_search_view_
= new views::ImageButton(this);
338 mic_search_view_
->set_id(VIEW_ID_MIC_SEARCH_BUTTON
);
339 mic_search_view_
->SetAccessibilityFocusable(true);
340 mic_search_view_
->SetTooltipText(
341 l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH
));
342 mic_search_view_
->SetImage(
343 views::Button::STATE_NORMAL
,
344 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
345 IDR_OMNIBOX_MIC_SEARCH
));
346 mic_search_view_
->SetImageAlignment(views::ImageButton::ALIGN_CENTER
,
347 views::ImageButton::ALIGN_MIDDLE
);
348 mic_search_view_
->SetVisible(false);
349 InitTouchableLocationBarChildView(mic_search_view_
);
350 AddChildView(mic_search_view_
);
352 for (int i
= 0; i
< CONTENT_SETTINGS_NUM_TYPES
; ++i
) {
353 ContentSettingImageView
* content_blocked_view
=
354 new ContentSettingImageView(static_cast<ContentSettingsType
>(i
), this,
355 bubble_font_list
, text_color
,
357 content_setting_views_
.push_back(content_blocked_view
);
358 content_blocked_view
->SetVisible(false);
359 AddChildView(content_blocked_view
);
362 generated_credit_card_view_
= new GeneratedCreditCardView(delegate_
);
363 AddChildView(generated_credit_card_view_
);
365 zoom_view_
= new ZoomView(delegate_
);
366 zoom_view_
->set_id(VIEW_ID_ZOOM_BUTTON
);
367 AddChildView(zoom_view_
);
369 open_pdf_in_reader_view_
= new OpenPDFInReaderView(this);
370 AddChildView(open_pdf_in_reader_view_
);
372 manage_passwords_icon_view_
= new ManagePasswordsIconView(delegate_
);
373 manage_passwords_icon_view_
->set_id(VIEW_ID_MANAGE_PASSWORDS_ICON_BUTTON
);
374 AddChildView(manage_passwords_icon_view_
);
376 translate_icon_view_
= new TranslateIconView(command_updater());
377 translate_icon_view_
->SetVisible(false);
378 AddChildView(translate_icon_view_
);
380 star_view_
= new StarView(command_updater());
381 star_view_
->SetVisible(false);
382 AddChildView(star_view_
);
384 search_button_
= new views::LabelButton(this, base::string16());
385 search_button_
->set_triggerable_event_flags(
386 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_MIDDLE_MOUSE_BUTTON
);
387 search_button_
->SetStyle(views::Button::STYLE_BUTTON
);
388 search_button_
->SetFocusable(false);
389 search_button_
->set_min_size(gfx::Size());
390 scoped_ptr
<views::LabelButtonBorder
> search_button_border(
391 new views::LabelButtonBorder(search_button_
->style()));
392 search_button_border
->set_insets(gfx::Insets());
393 const int kSearchButtonNormalImages
[] = IMAGE_GRID(IDR_OMNIBOX_SEARCH_BUTTON
);
394 search_button_border
->SetPainter(
395 false, views::Button::STATE_NORMAL
,
396 views::Painter::CreateImageGridPainter(kSearchButtonNormalImages
));
397 const int kSearchButtonHoveredImages
[] =
398 IMAGE_GRID(IDR_OMNIBOX_SEARCH_BUTTON_HOVER
);
399 search_button_border
->SetPainter(
400 false, views::Button::STATE_HOVERED
,
401 views::Painter::CreateImageGridPainter(kSearchButtonHoveredImages
));
402 const int kSearchButtonPressedImages
[] =
403 IMAGE_GRID(IDR_OMNIBOX_SEARCH_BUTTON_PRESSED
);
404 search_button_border
->SetPainter(
405 false, views::Button::STATE_PRESSED
,
406 views::Painter::CreateImageGridPainter(kSearchButtonPressedImages
));
407 search_button_border
->SetPainter(false, views::Button::STATE_DISABLED
, NULL
);
408 search_button_border
->SetPainter(true, views::Button::STATE_NORMAL
, NULL
);
409 search_button_border
->SetPainter(true, views::Button::STATE_HOVERED
, NULL
);
410 search_button_border
->SetPainter(true, views::Button::STATE_PRESSED
, NULL
);
411 search_button_border
->SetPainter(true, views::Button::STATE_DISABLED
, NULL
);
412 search_button_
->SetBorder(search_button_border
.PassAs
<views::Border
>());
413 const int kSearchButtonWidth
= 56;
414 search_button_
->set_min_size(gfx::Size(kSearchButtonWidth
, 0));
415 search_button_
->SetVisible(false);
416 AddChildView(search_button_
);
418 content::Source
<Profile
> profile_source
= content::Source
<Profile
>(profile());
420 chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED
,
422 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED
, profile_source
);
423 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED
, profile_source
);
425 // Initialize the location entry. We do this to avoid a black flash which is
426 // visible when the location entry has just been initialized.
430 bool LocationBarView::IsInitialized() const {
431 return omnibox_view_
!= NULL
;
434 SkColor
LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level
,
435 ColorKind kind
) const {
436 const ui::NativeTheme
* native_theme
= GetNativeTheme();
439 return native_theme
->GetSystemColor(
440 ui::NativeTheme::kColorId_TextfieldDefaultBackground
);
443 return native_theme
->GetSystemColor(
444 ui::NativeTheme::kColorId_TextfieldDefaultColor
);
447 return native_theme
->GetSystemColor(
448 ui::NativeTheme::kColorId_TextfieldSelectionColor
);
450 case DEEMPHASIZED_TEXT
:
451 return color_utils::AlphaBlend(
452 GetColor(security_level
, TEXT
),
453 GetColor(security_level
, BACKGROUND
),
456 case SECURITY_TEXT
: {
458 switch (security_level
) {
459 case ToolbarModel::EV_SECURE
:
460 case ToolbarModel::SECURE
:
461 color
= SkColorSetRGB(7, 149, 0);
464 case ToolbarModel::SECURITY_WARNING
:
465 case ToolbarModel::SECURITY_POLICY_WARNING
:
466 return GetColor(security_level
, DEEMPHASIZED_TEXT
);
469 case ToolbarModel::SECURITY_ERROR
:
470 color
= SkColorSetRGB(162, 0, 0);
475 return GetColor(security_level
, TEXT
);
477 return color_utils::GetReadableColor(
478 color
, GetColor(security_level
, BACKGROUND
));
483 return GetColor(security_level
, TEXT
);
487 void LocationBarView::GetOmniboxPopupPositioningInfo(
488 gfx::Point
* top_left_screen_coord
,
492 // Because the popup might appear atop the attached bookmark bar, there won't
493 // necessarily be a client edge separating it from the rest of the toolbar.
494 // Therefore we position the popup high enough so it can draw its own client
495 // edge at the top, in the same place the toolbar would normally draw the
497 *top_left_screen_coord
= gfx::Point(
499 parent()->height() - views::NonClientFrameView::kClientEdgeThickness
);
500 views::View::ConvertPointToScreen(parent(), top_left_screen_coord
);
501 *popup_width
= parent()->width();
503 gfx::Rect
location_bar_bounds(bounds());
504 location_bar_bounds
.Inset(kNormalEdgeThickness
, 0);
505 *left_margin
= location_bar_bounds
.x();
506 *right_margin
= *popup_width
- location_bar_bounds
.right();
510 int LocationBarView::GetItemPadding() {
511 const int kTouchItemPadding
= 8;
512 if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH
)
513 return kTouchItemPadding
;
515 const int kDesktopItemPadding
= 3;
516 return kDesktopItemPadding
;
519 // DropdownBarHostDelegate
520 void LocationBarView::SetFocusAndSelection(bool select_all
) {
521 FocusLocation(select_all
);
524 void LocationBarView::SetAnimationOffset(int offset
) {
525 animation_offset_
= offset
;
528 void LocationBarView::UpdateContentSettingsIcons() {
529 if (RefreshContentSettingViews()) {
535 void LocationBarView::UpdateManagePasswordsIconAndBubble() {
536 if (RefreshManagePasswordsIconView()) {
540 ShowManagePasswordsBubbleIfNeeded();
543 void LocationBarView::UpdatePageActions() {
544 size_t count_before
= page_action_views_
.size();
545 bool changed
= RefreshPageActionViews();
546 if (page_action_views_
.size() != count_before
) {
547 content::NotificationService::current()->Notify(
548 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED
,
549 content::Source
<LocationBar
>(this),
550 content::NotificationService::NoDetails());
559 void LocationBarView::InvalidatePageActions() {
560 size_t count_before
= page_action_views_
.size();
561 DeletePageActionViews();
562 if (page_action_views_
.size() != count_before
) {
563 content::NotificationService::current()->Notify(
564 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED
,
565 content::Source
<LocationBar
>(this),
566 content::NotificationService::NoDetails());
570 void LocationBarView::UpdateOpenPDFInReaderPrompt() {
571 open_pdf_in_reader_view_
->Update(
572 GetToolbarModel()->input_in_progress() ? NULL
: GetWebContents());
577 void LocationBarView::UpdateGeneratedCreditCardView() {
578 generated_credit_card_view_
->Update();
583 void LocationBarView::OnFocus() {
584 // Focus the view widget first which implements accessibility for
585 // Chrome OS. It is noop on Win. This should be removed once
586 // Chrome OS migrates to aura, which uses Views' textfield that receives
587 // focus. See crbug.com/106428.
588 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS
, false);
590 // Then focus the native location view which implements accessibility for
592 omnibox_view_
->SetFocus();
595 void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction
* page_action
,
596 bool preview_enabled
) {
601 WebContents
* contents
= delegate_
->GetWebContents();
603 RefreshPageActionViews();
604 PageActionWithBadgeView
* page_action_view
=
605 static_cast<PageActionWithBadgeView
*>(GetPageActionView(page_action
));
606 DCHECK(page_action_view
);
607 if (!page_action_view
)
610 page_action_view
->image_view()->set_preview_enabled(preview_enabled
);
611 page_action_view
->UpdateVisibility(contents
, GetToolbarModel()->GetURL());
616 views::View
* LocationBarView::GetPageActionView(ExtensionAction
*page_action
) {
618 for (PageActionViews::const_iterator
i(page_action_views_
.begin());
619 i
!= page_action_views_
.end(); ++i
) {
620 if ((*i
)->image_view()->page_action() == page_action
)
626 void LocationBarView::SetStarToggled(bool on
) {
628 star_view_
->SetToggled(on
);
631 void LocationBarView::SetTranslateIconToggled(bool on
) {
632 translate_icon_view_
->SetToggled(on
);
635 void LocationBarView::ShowBookmarkPrompt() {
636 if (star_view_
&& star_view_
->visible())
637 BookmarkPromptView::ShowPrompt(star_view_
, profile()->GetPrefs());
640 void LocationBarView::ZoomChangedForActiveTab(bool can_show_bubble
) {
642 if (RefreshZoomView()) {
647 if (can_show_bubble
&& zoom_view_
->visible() && delegate_
->GetWebContents())
648 ZoomBubbleView::ShowBubble(delegate_
->GetWebContents(), true);
651 gfx::Point
LocationBarView::GetOmniboxViewOrigin() const {
652 gfx::Point
origin(omnibox_view_
->bounds().origin());
653 // If the UI layout is RTL, the coordinate system is not transformed and
654 // therefore we need to adjust the X coordinate so that bubble appears on the
655 // right hand side of the location bar.
656 if (base::i18n::IsRTL())
657 origin
.set_x(width() - origin
.x());
658 views::View::ConvertPointToScreen(this, &origin
);
662 void LocationBarView::SetImeInlineAutocompletion(const base::string16
& text
) {
663 ime_inline_autocomplete_view_
->SetText(text
);
664 ime_inline_autocomplete_view_
->SetVisible(!text
.empty());
667 void LocationBarView::SetGrayTextAutocompletion(const base::string16
& text
) {
668 if (suggested_text_view_
->text() != text
) {
669 suggested_text_view_
->SetText(text
);
670 suggested_text_view_
->SetVisible(!text
.empty());
676 base::string16
LocationBarView::GetGrayTextAutocompletion() const {
677 return HasValidSuggestText() ? suggested_text_view_
->text()
681 gfx::Size
LocationBarView::GetPreferredSize() {
682 gfx::Size
background_min_size(border_painter_
->GetMinimumSize());
683 if (!IsInitialized())
684 return background_min_size
;
685 gfx::Size
search_button_min_size(search_button_
->GetMinimumSize());
686 gfx::Size
min_size(background_min_size
);
687 min_size
.SetToMax(search_button_min_size
);
689 background_min_size
.width() + search_button_min_size
.width());
693 void LocationBarView::Layout() {
694 if (!IsInitialized())
697 selected_keyword_view_
->SetVisible(false);
698 location_icon_view_
->SetVisible(false);
699 ev_bubble_view_
->SetVisible(false);
700 keyword_hint_view_
->SetVisible(false);
702 const int item_padding
= GetItemPadding();
703 // The textfield has 1 px of whitespace before the text in the RTL case only.
704 const int kEditLeadingInternalSpace
= base::i18n::IsRTL() ? 1 : 0;
705 LocationBarLayout
leading_decorations(
706 LocationBarLayout::LEFT_EDGE
, item_padding
- kEditLeadingInternalSpace
);
707 LocationBarLayout
trailing_decorations(LocationBarLayout::RIGHT_EDGE
,
710 const base::string16
keyword(omnibox_view_
->model()->keyword());
711 const bool is_keyword_hint(omnibox_view_
->model()->is_keyword_hint());
712 const int bubble_location_y
= vertical_edge_thickness() + kBubblePadding
;
713 // In some cases (e.g. fullscreen mode) we may have 0 height. We still want
714 // to position our child views in this case, because other things may be
715 // positioned relative to them (e.g. the "bookmark added" bubble if the user
717 const int location_height
= GetInternalHeight(false);
718 const int bubble_height
= std::max(location_height
- (kBubblePadding
* 2), 0);
719 if (!keyword
.empty() && !is_keyword_hint
) {
720 leading_decorations
.AddDecoration(bubble_location_y
, bubble_height
, true, 0,
721 kBubblePadding
, item_padding
, 0,
722 selected_keyword_view_
);
723 if (selected_keyword_view_
->keyword() != keyword
) {
724 selected_keyword_view_
->SetKeyword(keyword
);
725 const TemplateURL
* template_url
=
726 TemplateURLServiceFactory::GetForProfile(profile())->
727 GetTemplateURLForKeyword(keyword
);
729 (template_url
->GetType() == TemplateURL::OMNIBOX_API_EXTENSION
)) {
730 gfx::Image image
= extensions::OmniboxAPI::Get(profile())->
731 GetOmniboxIcon(template_url
->GetExtensionId());
732 selected_keyword_view_
->SetImage(image
.AsImageSkia());
733 selected_keyword_view_
->set_is_extension_icon(true);
735 selected_keyword_view_
->SetImage(
736 *(GetThemeProvider()->GetImageSkiaNamed(IDR_OMNIBOX_SEARCH
)));
737 selected_keyword_view_
->set_is_extension_icon(false);
740 } else if (!origin_chip_view_
&&
741 (GetToolbarModel()->GetSecurityLevel(false) == ToolbarModel::EV_SECURE
)) {
742 ev_bubble_view_
->SetLabel(GetToolbarModel()->GetEVCertName());
743 // The largest fraction of the omnibox that can be taken by the EV bubble.
744 const double kMaxBubbleFraction
= 0.5;
745 leading_decorations
.AddDecoration(bubble_location_y
, bubble_height
, false,
746 kMaxBubbleFraction
, kBubblePadding
,
747 item_padding
, 0, ev_bubble_view_
);
749 leading_decorations
.AddDecoration(
750 vertical_edge_thickness(), location_height
,
751 GetBuiltInHorizontalPaddingForChildViews(),
752 location_icon_view_
);
755 if (star_view_
->visible()) {
756 trailing_decorations
.AddDecoration(
757 vertical_edge_thickness(), location_height
,
758 GetBuiltInHorizontalPaddingForChildViews(), star_view_
);
760 if (translate_icon_view_
->visible()) {
761 trailing_decorations
.AddDecoration(
762 vertical_edge_thickness(), location_height
,
763 GetBuiltInHorizontalPaddingForChildViews(),
764 translate_icon_view_
);
766 if (open_pdf_in_reader_view_
->visible()) {
767 trailing_decorations
.AddDecoration(
768 vertical_edge_thickness(), location_height
,
769 GetBuiltInHorizontalPaddingForChildViews(),
770 open_pdf_in_reader_view_
);
772 if (manage_passwords_icon_view_
->visible()) {
773 trailing_decorations
.AddDecoration(vertical_edge_thickness(),
775 manage_passwords_icon_view_
);
777 for (PageActionViews::const_iterator
i(page_action_views_
.begin());
778 i
!= page_action_views_
.end(); ++i
) {
779 if ((*i
)->visible()) {
780 trailing_decorations
.AddDecoration(
781 vertical_edge_thickness(), location_height
,
782 GetBuiltInHorizontalPaddingForChildViews(), (*i
));
785 if (zoom_view_
->visible()) {
786 trailing_decorations
.AddDecoration(vertical_edge_thickness(),
787 location_height
, 0, zoom_view_
);
789 for (ContentSettingViews::const_reverse_iterator
i(
790 content_setting_views_
.rbegin()); i
!= content_setting_views_
.rend();
792 if ((*i
)->visible()) {
793 trailing_decorations
.AddDecoration(
794 bubble_location_y
, bubble_height
, false, 0, item_padding
,
795 item_padding
, GetBuiltInHorizontalPaddingForChildViews(), (*i
));
798 if (generated_credit_card_view_
->visible()) {
799 trailing_decorations
.AddDecoration(vertical_edge_thickness(),
801 generated_credit_card_view_
);
803 if (mic_search_view_
->visible()) {
804 trailing_decorations
.AddDecoration(vertical_edge_thickness(),
805 location_height
, 0, mic_search_view_
);
807 // Because IMEs may eat the tab key, we don't show "press tab to search" while
808 // IME composition is in progress.
809 if (!keyword
.empty() && is_keyword_hint
&& !omnibox_view_
->IsImeComposing()) {
810 trailing_decorations
.AddDecoration(vertical_edge_thickness(),
811 location_height
, true, 0, item_padding
,
812 item_padding
, 0, keyword_hint_view_
);
813 if (keyword_hint_view_
->keyword() != keyword
)
814 keyword_hint_view_
->SetKeyword(keyword
);
818 const int horizontal_edge_thickness
= GetHorizontalEdgeThickness();
819 int full_width
= width() - horizontal_edge_thickness
;
820 // The search button images are made to look as if they overlay the normal
821 // edge images, but to align things, the search button needs to be inset
822 // horizontally by 1 px.
823 const int kSearchButtonInset
= 1;
824 const gfx::Size
search_button_size(search_button_
->GetPreferredSize());
825 const int search_button_reserved_width
=
826 search_button_size
.width() + kSearchButtonInset
;
827 full_width
-= search_button_
->visible() ?
828 search_button_reserved_width
: horizontal_edge_thickness
;
829 int entry_width
= full_width
;
830 leading_decorations
.LayoutPass1(&entry_width
);
831 trailing_decorations
.LayoutPass1(&entry_width
);
832 leading_decorations
.LayoutPass2(&entry_width
);
833 trailing_decorations
.LayoutPass2(&entry_width
);
835 int location_needed_width
= omnibox_view_
->GetTextWidth();
836 int available_width
= entry_width
- location_needed_width
;
837 // The bounds must be wide enough for all the decorations to fit.
838 gfx::Rect
location_bounds(
839 horizontal_edge_thickness
, vertical_edge_thickness(),
840 std::max(full_width
, full_width
- entry_width
), location_height
);
841 leading_decorations
.LayoutPass3(&location_bounds
, &available_width
);
842 trailing_decorations
.LayoutPass3(&location_bounds
, &available_width
);
844 // Layout out the suggested text view right aligned to the location
845 // entry. Only show the suggested text if we can fit the text from one
846 // character before the end of the selection to the end of the text and the
847 // suggested text. If we can't it means either the suggested text is too big,
848 // or the user has scrolled.
850 // TODO(sky): We could potentially adjust this to take into account suggested
851 // text to force using minimum size if necessary, but currently the chance of
852 // showing keyword hints and suggested text is minimal and we're not confident
853 // this is the right approach for suggested text.
855 int omnibox_view_margin
= 0;
856 if (suggested_text_view_
->visible()) {
857 // We do not display the suggested text when it contains a mix of RTL and
858 // LTR characters since this could mean the suggestion should be displayed
859 // in the middle of the string.
860 base::i18n::TextDirection text_direction
=
861 base::i18n::GetStringDirection(omnibox_view_
->GetText());
862 if (text_direction
!=
863 base::i18n::GetStringDirection(suggested_text_view_
->text()))
864 text_direction
= base::i18n::UNKNOWN_DIRECTION
;
866 // TODO(sky): need to layout when the user changes caret position.
867 gfx::Size
suggested_text_size(suggested_text_view_
->GetPreferredSize());
868 if (suggested_text_size
.width() > available_width
||
869 text_direction
== base::i18n::UNKNOWN_DIRECTION
) {
870 // Hide the suggested text if the user has scrolled or we can't fit all
871 // the suggested text, or we have a mix of RTL and LTR characters.
872 suggested_text_view_
->SetBounds(0, 0, 0, 0);
874 location_needed_width
=
875 std::min(location_needed_width
,
876 location_bounds
.width() - suggested_text_size
.width());
877 gfx::Rect
suggested_text_bounds(location_bounds
.x(), location_bounds
.y(),
878 suggested_text_size
.width(),
879 location_bounds
.height());
880 // TODO(sky): figure out why this needs the -1.
881 suggested_text_bounds
.Offset(location_needed_width
- 1, 0);
883 // We reverse the order of the location entry and suggested text if:
884 // - Chrome is RTL but the text is fully LTR, or
885 // - Chrome is LTR but the text is fully RTL.
886 // This ensures the suggested text is correctly displayed to the right
887 // (or left) of the user text.
888 if (text_direction
== (base::i18n::IsRTL() ?
889 base::i18n::LEFT_TO_RIGHT
: base::i18n::RIGHT_TO_LEFT
)) {
890 // TODO(sky): Figure out why we need the +1.
891 suggested_text_bounds
.set_x(location_bounds
.x() + 1);
892 // Use a margin to prevent omnibox text from overlapping suggest text.
893 omnibox_view_margin
= suggested_text_bounds
.width();
895 suggested_text_view_
->SetBoundsRect(suggested_text_bounds
);
899 const gfx::Insets insets
= omnibox_view_
->GetInsets();
900 omnibox_view_
->SetBorder(views::Border::CreateEmptyBorder(
901 insets
.top(), insets
.left(), insets
.bottom(), omnibox_view_margin
));
903 // Layout |ime_inline_autocomplete_view_| next to the user input.
904 if (ime_inline_autocomplete_view_
->visible()) {
906 gfx::GetStringWidth(ime_inline_autocomplete_view_
->text(),
907 ime_inline_autocomplete_view_
->font_list()) +
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
)
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
), location_bounds
.height());
922 omnibox_view_
->SetBoundsRect(location_bounds
);
924 search_button_
->SetBoundsRect(gfx::Rect(
925 gfx::Point(width() - search_button_reserved_width
, 0),
926 search_button_size
));
929 void LocationBarView::PaintChildren(gfx::Canvas
* canvas
) {
930 View::PaintChildren(canvas
);
932 // For non-InstantExtendedAPI cases, if necessary, show focus rect. As we need
933 // the focus rect to appear on top of children we paint here rather than
935 // Note: |Canvas::DrawFocusRect| paints a dashed rect with gray color.
936 if (show_focus_rect_
&& HasFocus())
937 canvas
->DrawFocusRect(omnibox_view_
->bounds());
939 // Maximized popup windows don't draw the horizontal edges. We implement this
940 // by simply expanding the paint area outside the view by the edge thickness.
941 gfx::Rect
border_rect(GetContentsBounds());
942 if (is_popup_mode_
&& (GetHorizontalEdgeThickness() == 0))
943 border_rect
.Inset(-kPopupEdgeThickness
, 0);
944 views::Painter::PaintPainterAt(canvas
, border_painter_
.get(), border_rect
);
947 void LocationBarView::OnPaint(gfx::Canvas
* canvas
) {
948 View::OnPaint(canvas
);
950 // Fill the location bar background color behind the border. Parts of the
951 // border images are meant to rest atop the toolbar background and parts atop
952 // the omnibox background, so we can't just blindly fill our entire bounds.
953 gfx::Rect
bounds(GetContentsBounds());
954 bounds
.Inset(GetHorizontalEdgeThickness(), vertical_edge_thickness());
955 SkColor
color(GetColor(ToolbarModel::NONE
, BACKGROUND
));
956 if (is_popup_mode_
) {
957 canvas
->FillRect(bounds
, color
);
960 paint
.setStyle(SkPaint::kFill_Style
);
961 paint
.setColor(color
);
962 const int kBorderCornerRadius
= 2;
963 canvas
->DrawRoundRect(bounds
, kBorderCornerRadius
, paint
);
966 // The border itself will be drawn in PaintChildren() since it includes an
967 // inner shadow which should be drawn over the contents.
970 void LocationBarView::SetShowFocusRect(bool show
) {
971 show_focus_rect_
= show
;
975 void LocationBarView::SelectAll() {
976 omnibox_view_
->SelectAll(true);
979 views::ImageView
* LocationBarView::GetLocationIconView() {
980 return origin_chip_view_
?
981 origin_chip_view_
->location_icon_view() : location_icon_view_
;
984 const views::ImageView
* LocationBarView::GetLocationIconView() const {
985 return origin_chip_view_
?
986 origin_chip_view_
->location_icon_view() : location_icon_view_
;
989 views::View
* LocationBarView::GetLocationBarAnchor() {
990 return GetLocationIconView();
993 gfx::Point
LocationBarView::GetLocationBarAnchorPoint() const {
994 // The +1 in the next line creates a 1-px gap between icon and arrow tip.
995 gfx::Point
icon_bottom(0, GetLocationIconView()->GetImageBounds().bottom() -
996 LocationBarView::kIconInternalPadding
+ 1);
997 gfx::Point
icon_center(GetLocationIconView()->GetImageBounds().CenterPoint());
998 gfx::Point
point(icon_center
.x(), icon_bottom
.y());
999 ConvertPointToTarget(GetLocationIconView(), this, &point
);
1003 views::View
* LocationBarView::generated_credit_card_view() {
1004 return generated_credit_card_view_
;
1007 void LocationBarView::Update(const WebContents
* contents
) {
1008 mic_search_view_
->SetVisible(
1009 !GetToolbarModel()->input_in_progress() && browser_
&&
1010 browser_
->search_model()->voice_search_supported());
1011 RefreshContentSettingViews();
1012 generated_credit_card_view_
->Update();
1013 ZoomBubbleView::CloseBubble();
1015 RefreshPageActionViews();
1016 RefreshTranslateIcon();
1017 RefreshManagePasswordsIconView();
1018 open_pdf_in_reader_view_
->Update(
1019 GetToolbarModel()->input_in_progress() ? NULL
: GetWebContents());
1022 star_view_
->SetVisible(
1023 browser_defaults::bookmarks_enabled
&& !is_popup_mode_
&&
1024 !GetToolbarModel()->input_in_progress() &&
1025 edit_bookmarks_enabled_
.GetValue() &&
1026 !IsBookmarkStarHiddenByExtension());
1030 omnibox_view_
->OnTabChanged(contents
);
1032 omnibox_view_
->Update();
1034 OnChanged(); // NOTE: Calls Layout().
1037 void LocationBarView::OnChanged() {
1038 int icon_id
= omnibox_view_
->GetIcon();
1039 location_icon_view_
->SetImage(GetThemeProvider()->GetImageSkiaNamed(icon_id
));
1040 location_icon_view_
->ShowTooltip(!GetOmniboxView()->IsEditingOrEmpty());
1042 ToolbarModel
* toolbar_model
= GetToolbarModel();
1043 chrome::DisplaySearchButtonConditions conditions
=
1044 chrome::GetDisplaySearchButtonConditions();
1045 bool meets_conditions
=
1046 (conditions
== chrome::DISPLAY_SEARCH_BUTTON_ALWAYS
) ||
1047 ((conditions
!= chrome::DISPLAY_SEARCH_BUTTON_NEVER
) &&
1048 (toolbar_model
->WouldPerformSearchTermReplacement(true) ||
1049 ((conditions
== chrome::DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP
) &&
1050 toolbar_model
->input_in_progress())));
1051 search_button_
->SetVisible(!is_popup_mode_
&& meets_conditions
);
1052 search_button_
->SetImage(
1053 views::Button::STATE_NORMAL
,
1054 *GetThemeProvider()->GetImageSkiaNamed((icon_id
== IDR_OMNIBOX_SEARCH
) ?
1055 IDR_OMNIBOX_SEARCH_BUTTON_LOUPE
: IDR_OMNIBOX_SEARCH_BUTTON_ARROW
));
1057 if (origin_chip_view_
)
1058 origin_chip_view_
->OnChanged();
1064 void LocationBarView::OnSetFocus() {
1065 GetFocusManager()->SetFocusedView(this);
1068 InstantController
* LocationBarView::GetInstant() {
1069 return delegate_
->GetInstant();
1072 WebContents
* LocationBarView::GetWebContents() {
1073 return delegate_
->GetWebContents();
1076 ToolbarModel
* LocationBarView::GetToolbarModel() {
1077 return delegate_
->GetToolbarModel();
1080 const ToolbarModel
* LocationBarView::GetToolbarModel() const {
1081 return delegate_
->GetToolbarModel();
1084 const char* LocationBarView::GetClassName() const {
1085 return kViewClassName
;
1088 bool LocationBarView::HasFocus() const {
1089 return omnibox_view_
->model()->has_focus();
1092 void LocationBarView::GetAccessibleState(ui::AccessibleViewState
* state
) {
1093 if (!IsInitialized())
1096 state
->role
= ui::AccessibilityTypes::ROLE_LOCATION_BAR
;
1097 state
->name
= l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION
);
1098 state
->value
= omnibox_view_
->GetText();
1100 base::string16::size_type entry_start
;
1101 base::string16::size_type entry_end
;
1102 omnibox_view_
->GetSelectionBounds(&entry_start
, &entry_end
);
1103 state
->selection_start
= entry_start
;
1104 state
->selection_end
= entry_end
;
1106 if (is_popup_mode_
) {
1107 state
->state
|= ui::AccessibilityTypes::STATE_READONLY
;
1109 state
->set_value_callback
=
1110 base::Bind(&LocationBarView::AccessibilitySetValue
,
1111 weak_ptr_factory_
.GetWeakPtr());
1115 void LocationBarView::OnBoundsChanged(const gfx::Rect
& previous_bounds
) {
1116 InstantServiceFactory::GetForProfile(profile())->OnOmniboxStartMarginChanged(
1119 OmniboxPopupView
* popup
= omnibox_view_
->model()->popup_model()->view();
1120 if (popup
->IsOpen())
1121 popup
->UpdatePopupAppearance();
1124 void LocationBarView::ButtonPressed(views::Button
* sender
,
1125 const ui::Event
& event
) {
1126 if (sender
== mic_search_view_
) {
1127 command_updater()->ExecuteCommand(IDC_TOGGLE_SPEECH_INPUT
);
1131 DCHECK_EQ(search_button_
, sender
);
1132 // TODO(pkasting): When macourteau adds UMA stats for this, wire them up here.
1133 omnibox_view_
->model()->AcceptInput(
1134 ui::DispositionFromEventFlags(event
.flags()), false);
1137 void LocationBarView::WriteDragDataForView(views::View
* sender
,
1138 const gfx::Point
& press_pt
,
1139 OSExchangeData
* data
) {
1140 DCHECK_NE(GetDragOperationsForView(sender
, press_pt
),
1141 ui::DragDropTypes::DRAG_NONE
);
1143 WebContents
* web_contents
= GetWebContents();
1144 FaviconTabHelper
* favicon_tab_helper
=
1145 FaviconTabHelper::FromWebContents(web_contents
);
1146 gfx::ImageSkia favicon
= favicon_tab_helper
->GetFavicon().AsImageSkia();
1147 button_drag_utils::SetURLAndDragImage(web_contents
->GetURL(),
1148 web_contents
->GetTitle(),
1151 sender
->GetWidget());
1154 int LocationBarView::GetDragOperationsForView(views::View
* sender
,
1155 const gfx::Point
& p
) {
1156 DCHECK((sender
== location_icon_view_
) || (sender
== ev_bubble_view_
));
1157 WebContents
* web_contents
= delegate_
->GetWebContents();
1158 return (web_contents
&& web_contents
->GetURL().is_valid() &&
1159 !GetOmniboxView()->IsEditingOrEmpty()) ?
1160 (ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
) :
1161 ui::DragDropTypes::DRAG_NONE
;
1164 bool LocationBarView::CanStartDragForView(View
* sender
,
1165 const gfx::Point
& press_pt
,
1166 const gfx::Point
& p
) {
1170 ////////////////////////////////////////////////////////////////////////////////
1171 // LocationBarView, LocationBar implementation:
1173 void LocationBarView::ShowFirstRunBubble() {
1174 // Wait until search engines have loaded to show the first run bubble.
1175 TemplateURLService
* url_service
=
1176 TemplateURLServiceFactory::GetForProfile(profile());
1177 if (!url_service
->loaded()) {
1178 template_url_service_
= url_service
;
1179 template_url_service_
->AddObserver(this);
1180 template_url_service_
->Load();
1183 ShowFirstRunBubbleInternal();
1186 GURL
LocationBarView::GetDestinationURL() const {
1187 return destination_url();
1190 WindowOpenDisposition
LocationBarView::GetWindowOpenDisposition() const {
1191 return disposition();
1194 content::PageTransition
LocationBarView::GetPageTransition() const {
1195 return transition();
1198 void LocationBarView::AcceptInput() {
1199 omnibox_view_
->model()->AcceptInput(CURRENT_TAB
, false);
1202 void LocationBarView::FocusLocation(bool select_all
) {
1203 omnibox_view_
->SetFocus();
1205 omnibox_view_
->SelectAll(true);
1208 void LocationBarView::FocusSearch() {
1209 omnibox_view_
->SetFocus();
1210 omnibox_view_
->SetForcedQuery();
1213 void LocationBarView::SaveStateToContents(WebContents
* contents
) {
1214 omnibox_view_
->SaveStateToTab(contents
);
1217 void LocationBarView::Revert() {
1218 omnibox_view_
->RevertAll();
1221 const OmniboxView
* LocationBarView::GetOmniboxView() const {
1222 return omnibox_view_
;
1225 OmniboxView
* LocationBarView::GetOmniboxView() {
1226 return omnibox_view_
;
1229 LocationBarTesting
* LocationBarView::GetLocationBarForTesting() {
1233 int LocationBarView::PageActionCount() {
1234 return page_action_views_
.size();
1237 int LocationBarView::PageActionVisibleCount() {
1239 for (size_t i
= 0; i
< page_action_views_
.size(); i
++) {
1240 if (page_action_views_
[i
]->visible())
1246 ExtensionAction
* LocationBarView::GetPageAction(size_t index
) {
1247 if (index
< page_action_views_
.size())
1248 return page_action_views_
[index
]->image_view()->page_action();
1254 ExtensionAction
* LocationBarView::GetVisiblePageAction(size_t index
) {
1256 for (size_t i
= 0; i
< page_action_views_
.size(); ++i
) {
1257 if (page_action_views_
[i
]->visible()) {
1258 if (current
== index
)
1259 return page_action_views_
[i
]->image_view()->page_action();
1269 void LocationBarView::TestPageActionPressed(size_t index
) {
1271 for (size_t i
= 0; i
< page_action_views_
.size(); ++i
) {
1272 if (page_action_views_
[i
]->visible()) {
1273 if (current
== index
) {
1274 page_action_views_
[i
]->image_view()->ExecuteAction(
1275 ExtensionPopup::SHOW
);
1285 bool LocationBarView::GetBookmarkStarVisibility() {
1287 return star_view_
->visible();
1290 void LocationBarView::OnTemplateURLServiceChanged() {
1291 template_url_service_
->RemoveObserver(this);
1292 template_url_service_
= NULL
;
1293 // If the browser is no longer active, let's not show the info bubble, as this
1294 // would make the browser the active window again.
1295 if (omnibox_view_
&& omnibox_view_
->GetWidget()->IsActive())
1296 ShowFirstRunBubble();
1299 void LocationBarView::Observe(int type
,
1300 const content::NotificationSource
& source
,
1301 const content::NotificationDetails
& details
) {
1303 case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED
: {
1304 // Only update if the updated action box was for the active tab contents.
1305 WebContents
* target_tab
= content::Details
<WebContents
>(details
).ptr();
1306 if (target_tab
== GetWebContents())
1307 UpdatePageActions();
1311 case chrome::NOTIFICATION_EXTENSION_LOADED
:
1312 case chrome::NOTIFICATION_EXTENSION_UNLOADED
:
1317 NOTREACHED() << "Unexpected notification.";
1321 void LocationBarView::ModelChanged(const SearchModel::State
& old_state
,
1322 const SearchModel::State
& new_state
) {
1323 const bool visible
= !GetToolbarModel()->input_in_progress() &&
1324 new_state
.voice_search_supported
;
1325 if (mic_search_view_
->visible() != visible
) {
1326 mic_search_view_
->SetVisible(visible
);
1331 int LocationBarView::GetInternalHeight(bool use_preferred_size
) {
1333 use_preferred_size
? GetPreferredSize().height() : height();
1334 return std::max(total_height
- (vertical_edge_thickness() * 2), 0);
1337 ////////////////////////////////////////////////////////////////////////////////
1338 // LocationBarView, private:
1341 int LocationBarView::GetBuiltInHorizontalPaddingForChildViews() {
1342 return (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH
) ?
1343 GetItemPadding() / 2 : 0;
1346 int LocationBarView::GetHorizontalEdgeThickness() const {
1347 // In maximized popup mode, there isn't any edge.
1348 return (is_popup_mode_
&& browser_
&& browser_
->window() &&
1349 browser_
->window()->IsMaximized()) ? 0 : vertical_edge_thickness();
1352 bool LocationBarView::RefreshContentSettingViews() {
1353 bool visibility_changed
= false;
1354 for (ContentSettingViews::const_iterator
i(content_setting_views_
.begin());
1355 i
!= content_setting_views_
.end(); ++i
) {
1356 const bool was_visible
= (*i
)->visible();
1357 (*i
)->Update(GetToolbarModel()->input_in_progress() ?
1358 NULL
: GetWebContents());
1359 if (was_visible
!= (*i
)->visible())
1360 visibility_changed
= true;
1362 return visibility_changed
;
1365 void LocationBarView::DeletePageActionViews() {
1366 for (PageActionViews::const_iterator
i(page_action_views_
.begin());
1367 i
!= page_action_views_
.end(); ++i
)
1368 RemoveChildView(*i
);
1369 STLDeleteElements(&page_action_views_
);
1372 bool LocationBarView::RefreshPageActionViews() {
1376 bool changed
= false;
1378 // Remember the previous visibility of the page actions so that we can
1379 // notify when this changes.
1380 std::map
<ExtensionAction
*, bool> old_visibility
;
1381 for (PageActionViews::const_iterator
i(page_action_views_
.begin());
1382 i
!= page_action_views_
.end(); ++i
) {
1383 old_visibility
[(*i
)->image_view()->page_action()] = (*i
)->visible();
1386 PageActions new_page_actions
;
1388 WebContents
* contents
= delegate_
->GetWebContents();
1390 extensions::TabHelper
* extensions_tab_helper
=
1391 extensions::TabHelper::FromWebContents(contents
);
1392 extensions::LocationBarController
* controller
=
1393 extensions_tab_helper
->location_bar_controller();
1394 new_page_actions
= controller
->GetCurrentActions();
1397 // On startup we sometimes haven't loaded any extensions. This makes sure
1398 // we catch up when the extensions (and any page actions) load.
1399 if (page_actions_
!= new_page_actions
) {
1402 page_actions_
.swap(new_page_actions
);
1403 DeletePageActionViews(); // Delete the old views (if any).
1405 // Create the page action views.
1406 for (PageActions::const_iterator i
= page_actions_
.begin();
1407 i
!= page_actions_
.end(); ++i
) {
1408 PageActionWithBadgeView
* page_action_view
= new PageActionWithBadgeView(
1409 delegate_
->CreatePageActionImageView(this, *i
));
1410 page_action_view
->SetVisible(false);
1411 page_action_views_
.push_back(page_action_view
);
1414 // Move rightmost extensions to the start.
1415 std::stable_partition(
1416 page_action_views_
.begin(),
1417 page_action_views_
.end(),
1418 IsPageActionViewRightAligned(
1419 extensions::ExtensionSystem::Get(profile())->extension_service()));
1421 View
* right_anchor
= open_pdf_in_reader_view_
;
1423 right_anchor
= star_view_
;
1424 DCHECK(right_anchor
);
1426 // |page_action_views_| are ordered right-to-left. Add them as children in
1427 // reverse order so the logical order and visual order match for
1428 // accessibility purposes.
1429 for (PageActionViews::reverse_iterator i
= page_action_views_
.rbegin();
1430 i
!= page_action_views_
.rend(); ++i
)
1431 AddChildViewAt(*i
, GetIndexOf(right_anchor
));
1434 if (!page_action_views_
.empty() && contents
) {
1435 Browser
* browser
= chrome::FindBrowserWithWebContents(contents
);
1436 GURL url
= browser
->tab_strip_model()->GetActiveWebContents()->GetURL();
1438 for (PageActionViews::const_iterator
i(page_action_views_
.begin());
1439 i
!= page_action_views_
.end(); ++i
) {
1440 (*i
)->UpdateVisibility(
1441 GetToolbarModel()->input_in_progress() ? NULL
: contents
, url
);
1443 // Check if the visibility of the action changed and notify if it did.
1444 ExtensionAction
* action
= (*i
)->image_view()->page_action();
1445 if (old_visibility
.find(action
) == old_visibility
.end() ||
1446 old_visibility
[action
] != (*i
)->visible()) {
1448 content::NotificationService::current()->Notify(
1449 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED
,
1450 content::Source
<ExtensionAction
>(action
),
1451 content::Details
<WebContents
>(contents
));
1458 bool LocationBarView::RefreshZoomView() {
1460 WebContents
* web_contents
= GetWebContents();
1463 const bool was_visible
= zoom_view_
->visible();
1464 zoom_view_
->Update(ZoomController::FromWebContents(web_contents
));
1465 return was_visible
!= zoom_view_
->visible();
1468 bool LocationBarView::RefreshManagePasswordsIconView() {
1469 DCHECK(manage_passwords_icon_view_
);
1470 WebContents
* web_contents
= GetWebContents();
1473 const bool was_visible
= manage_passwords_icon_view_
->visible();
1474 manage_passwords_icon_view_
->Update(
1475 ManagePasswordsBubbleUIController::FromWebContents(web_contents
));
1476 return was_visible
!= manage_passwords_icon_view_
->visible();
1479 void LocationBarView::RefreshTranslateIcon() {
1480 if (!TranslateService::IsTranslateBubbleEnabled())
1483 WebContents
* web_contents
= GetWebContents();
1486 LanguageState
& language_state
= TranslateTabHelper::FromWebContents(
1487 web_contents
)->GetLanguageState();
1488 bool enabled
= language_state
.translate_enabled();
1489 command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE
, enabled
);
1490 translate_icon_view_
->SetVisible(enabled
);
1491 translate_icon_view_
->SetToggled(language_state
.IsPageTranslated());
1494 void LocationBarView::ShowManagePasswordsBubbleIfNeeded() {
1495 DCHECK(manage_passwords_icon_view_
);
1496 WebContents
* web_contents
= GetWebContents();
1499 manage_passwords_icon_view_
->ShowBubbleIfNeeded(
1500 ManagePasswordsBubbleUIController::FromWebContents(web_contents
));
1503 bool LocationBarView::HasValidSuggestText() const {
1504 return suggested_text_view_
->visible() &&
1505 !suggested_text_view_
->size().IsEmpty();
1508 void LocationBarView::ShowFirstRunBubbleInternal() {
1509 #if !defined(OS_CHROMEOS)
1510 // First run bubble doesn't make sense for Chrome OS.
1511 Browser
* browser
= GetBrowserFromDelegate(delegate_
);
1513 return; // Possible when browser is shutting down.
1515 FirstRunBubble::ShowBubble(browser
, GetLocationBarAnchor());
1519 void LocationBarView::AccessibilitySetValue(const base::string16
& new_value
) {
1520 omnibox_view_
->SetUserText(new_value
, new_value
, true);