1 // Copyright 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/gtk/location_bar_view_gtk.h"
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h"
15 #include "base/i18n/rtl.h"
16 #include "base/logging.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chrome/app/chrome_command_ids.h"
23 #include "chrome/browser/accessibility/accessibility_events.h"
24 #include "chrome/browser/accessibility/accessibility_extension_api.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/command_updater.h"
27 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
28 #include "chrome/browser/defaults.h"
29 #include "chrome/browser/extensions/api/commands/command_service.h"
30 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
31 #include "chrome/browser/extensions/extension_action.h"
32 #include "chrome/browser/extensions/extension_service.h"
33 #include "chrome/browser/extensions/extension_tab_util.h"
34 #include "chrome/browser/extensions/location_bar_controller.h"
35 #include "chrome/browser/extensions/tab_helper.h"
36 #include "chrome/browser/favicon/favicon_tab_helper.h"
37 #include "chrome/browser/search/instant_service.h"
38 #include "chrome/browser/search/instant_service_factory.h"
39 #include "chrome/browser/search_engines/template_url.h"
40 #include "chrome/browser/search_engines/template_url_service.h"
41 #include "chrome/browser/search_engines/template_url_service_factory.h"
42 #include "chrome/browser/themes/theme_properties.h"
43 #include "chrome/browser/ui/browser.h"
44 #include "chrome/browser/ui/browser_command_controller.h"
45 #include "chrome/browser/ui/browser_commands.h"
46 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
47 #include "chrome/browser/ui/browser_instant_controller.h"
48 #include "chrome/browser/ui/browser_list.h"
49 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
50 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
51 #include "chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.h"
52 #include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
53 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
54 #include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h"
55 #include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h"
56 #include "chrome/browser/ui/gtk/first_run_bubble.h"
57 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
58 #include "chrome/browser/ui/gtk/gtk_util.h"
59 #include "chrome/browser/ui/gtk/manage_passwords_bubble_gtk.h"
60 #include "chrome/browser/ui/gtk/nine_box.h"
61 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h"
62 #include "chrome/browser/ui/gtk/rounded_window.h"
63 #include "chrome/browser/ui/gtk/view_id_util.h"
64 #include "chrome/browser/ui/gtk/zoom_bubble_gtk.h"
65 #include "chrome/browser/ui/omnibox/location_bar_util.h"
66 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
67 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
68 #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h"
69 #include "chrome/browser/ui/tabs/tab_strip_model.h"
70 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h"
71 #include "chrome/browser/ui/zoom/zoom_controller.h"
72 #include "chrome/common/badge_util.h"
73 #include "chrome/common/chrome_switches.h"
74 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
75 #include "chrome/common/pref_names.h"
76 #include "content/public/browser/navigation_entry.h"
77 #include "content/public/browser/notification_service.h"
78 #include "content/public/browser/web_contents.h"
79 #include "extensions/common/extension.h"
80 #include "extensions/common/feature_switch.h"
81 #include "grit/generated_resources.h"
82 #include "grit/theme_resources.h"
83 #include "net/base/net_util.h"
84 #include "ui/base/accelerators/platform_accelerator_gtk.h"
85 #include "ui/base/accessibility/accessibility_types.h"
86 #include "ui/base/dragdrop/gtk_dnd_util.h"
87 #include "ui/base/gtk/gtk_hig_constants.h"
88 #include "ui/base/gtk/gtk_signal_registrar.h"
89 #include "ui/base/l10n/l10n_util.h"
90 #include "ui/base/resource/resource_bundle.h"
91 #include "ui/base/window_open_disposition.h"
92 #include "ui/gfx/canvas_skia_paint.h"
93 #include "ui/gfx/font.h"
94 #include "ui/gfx/gtk_util.h"
95 #include "ui/gfx/image/image.h"
97 using content::NavigationEntry
;
98 using content::OpenURLParams
;
99 using content::WebContents
;
100 using extensions::LocationBarController
;
101 using extensions::Extension
;
105 // We draw a border on the top and bottom (but not on left or right).
106 const int kBorderThickness
= 1;
108 const int kPopupEdgeThickness
= 1;
109 const int kNormalEdgeThickness
= 2;
111 // Spacing needed to align the bubble with the left side of the omnibox.
112 const int kFirstRunBubbleLeftSpacing
= 4;
114 // The padding around the top, bottom, and sides of the location bar hbox.
115 // We don't want to edit control's text to be right against the edge,
116 // as well the tab to search box and other widgets need to have the padding on
117 // top and bottom to avoid drawing larger than the location bar space.
118 const int kHboxBorder
= 2;
120 // Padding between the elements in the bar.
121 const int kInnerPadding
= 2;
123 // Colors used to draw the EV certificate rounded bubble.
124 const GdkColor kEvSecureTextColor
= GDK_COLOR_RGB(0x07, 0x95, 0x00);
125 const GdkColor kEvSecureBackgroundColor
= GDK_COLOR_RGB(0xef, 0xfc, 0xef);
126 const GdkColor kEvSecureBorderColor
= GDK_COLOR_RGB(0x90, 0xc3, 0x90);
128 // Colors used to draw the Tab to Search rounded bubble.
129 const GdkColor kKeywordBackgroundColor
= GDK_COLOR_RGB(0xf0, 0xf4, 0xfa);
130 const GdkColor kKeywordBorderColor
= GDK_COLOR_RGB(0xcb, 0xde, 0xf7);
132 // Use weak gray for showing search and keyword hint text.
133 const GdkColor kHintTextColor
= GDK_COLOR_RGB(0x75, 0x75, 0x75);
135 // Size of the rounding of the "Search site for:" box.
136 const int kCornerSize
= 3;
138 // Default page tool animation time (open and close). In ms.
139 const int kPageToolAnimationTime
= 150;
141 // The time, in ms, that the content setting label is fully displayed, for the
142 // cases where we animate it into and out of view.
143 const int kContentSettingImageDisplayTime
= 3200;
144 // The time, in ms, of the animation (open and close).
145 const int kContentSettingImageAnimationTime
= 150;
147 // Color of border of content setting area (icon/label).
148 const GdkColor kContentSettingBorderColor
= GDK_COLOR_RGB(0xe9, 0xb9, 0x66);
149 // Colors for the background gradient.
150 const GdkColor kContentSettingTopColor
= GDK_COLOR_RGB(0xff, 0xf8, 0xd4);
151 const GdkColor kContentSettingBottomColor
= GDK_COLOR_RGB(0xff, 0xe6, 0xaf);
153 // If widget is visible, increment the int pointed to by count.
154 // Suitible for use with gtk_container_foreach.
155 void CountVisibleWidgets(GtkWidget
* widget
, gpointer count
) {
156 if (gtk_widget_get_visible(widget
))
157 *static_cast<int*>(count
) += 1;
160 class ContentSettingImageViewGtk
: public LocationBarViewGtk::PageToolViewGtk
,
161 public BubbleDelegateGtk
{
163 ContentSettingImageViewGtk(ContentSettingsType content_type
,
164 LocationBarViewGtk
* parent
);
165 virtual ~ContentSettingImageViewGtk();
168 virtual void Update(WebContents
* web_contents
) OVERRIDE
;
170 // gfx::AnimationDelegate
171 virtual void AnimationEnded(const gfx::Animation
* animation
) OVERRIDE
;
175 virtual GdkColor
GetButtonBorderColor() const OVERRIDE
;
176 virtual GdkColor
GetGradientTopColor() const OVERRIDE
;
177 virtual GdkColor
GetGradientBottomColor() const OVERRIDE
;
178 virtual void OnClick(GtkWidget
* sender
) OVERRIDE
;
181 virtual void BubbleClosing(BubbleGtk
* bubble
,
182 bool closed_by_escape
) OVERRIDE
;
184 // The owning LocationBarViewGtk.
185 LocationBarViewGtk
* parent_
;
187 scoped_ptr
<ContentSettingImageModel
> content_setting_image_model_
;
189 // The currently shown bubble if any.
190 ContentSettingBubbleGtk
* content_setting_bubble_
;
192 DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk
);
195 ContentSettingImageViewGtk::ContentSettingImageViewGtk(
196 ContentSettingsType content_type
,
197 LocationBarViewGtk
* parent
)
200 content_setting_image_model_(
201 ContentSettingImageModel::CreateContentSettingImageModel(
203 content_setting_bubble_(NULL
) {
204 animation_
.SetSlideDuration(kContentSettingImageAnimationTime
);
207 ContentSettingImageViewGtk::~ContentSettingImageViewGtk() {
208 if (content_setting_bubble_
)
209 content_setting_bubble_
->Close();
212 void ContentSettingImageViewGtk::Update(WebContents
* web_contents
) {
214 content_setting_image_model_
->UpdateFromWebContents(web_contents
);
216 if (!content_setting_image_model_
->is_visible()) {
217 gtk_widget_hide(widget());
221 gtk_image_set_from_pixbuf(GTK_IMAGE(image_
.get()),
222 GtkThemeService::GetFrom(parent_
->browser()->profile())->GetImageNamed(
223 content_setting_image_model_
->get_icon()).ToGdkPixbuf());
225 gtk_widget_set_tooltip_text(widget(),
226 content_setting_image_model_
->get_tooltip().c_str());
227 gtk_widget_show_all(widget());
232 TabSpecificContentSettings
* content_settings
=
233 TabSpecificContentSettings::FromWebContents(web_contents
);
234 if (!content_settings
|| content_settings
->IsBlockageIndicated(
235 content_setting_image_model_
->get_content_settings_type()))
238 // The content blockage was not yet indicated to the user. Start indication
239 // animation and clear "not yet shown" flag.
240 content_settings
->SetBlockageHasBeenIndicated(
241 content_setting_image_model_
->get_content_settings_type());
243 int label_string_id
=
244 content_setting_image_model_
->explanatory_string_id();
245 // If there's no string for the content type, we don't animate.
246 if (!label_string_id
)
249 gtk_label_set_text(GTK_LABEL(label_
.get()),
250 l10n_util::GetStringUTF8(label_string_id
).c_str());
254 void ContentSettingImageViewGtk::AnimationEnded(
255 const gfx::Animation
* animation
) {
256 if (animation_
.IsShowing()) {
257 base::MessageLoop::current()->PostDelayedTask(
259 base::Bind(&ContentSettingImageViewGtk::CloseAnimation
,
260 weak_factory_
.GetWeakPtr()),
261 base::TimeDelta::FromMilliseconds(kContentSettingImageDisplayTime
));
263 gtk_widget_hide(label_
.get());
264 gtk_util::StopActingAsRoundedWindow(event_box_
.get());
265 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_
.get()), FALSE
);
269 GdkColor
ContentSettingImageViewGtk::GetButtonBorderColor() const {
270 return kContentSettingBorderColor
;
273 GdkColor
ContentSettingImageViewGtk::GetGradientTopColor() const {
274 return kContentSettingTopColor
;
277 GdkColor
ContentSettingImageViewGtk::GetGradientBottomColor() const {
278 return kContentSettingBottomColor
;
281 void ContentSettingImageViewGtk::OnClick(
283 WebContents
* web_contents
= parent_
->GetWebContents();
286 Profile
* profile
= parent_
->browser()->profile();
287 content_setting_bubble_
= new ContentSettingBubbleGtk(
289 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
290 parent_
->browser()->content_setting_bubble_model_delegate(),
293 content_setting_image_model_
->get_content_settings_type()),
298 void ContentSettingImageViewGtk::BubbleClosing(
300 bool closed_by_escape
) {
301 content_setting_bubble_
= NULL
;
304 gfx::Rect
AllocationToRect(const GtkAllocation
& allocation
) {
305 return gfx::Rect(allocation
.x
, allocation
.y
,
306 allocation
.width
, allocation
.height
);
311 ////////////////////////////////////////////////////////////////////////////////
312 // LocationBarViewGtk
315 const GdkColor
LocationBarViewGtk::kBackgroundColor
=
316 GDK_COLOR_RGB(255, 255, 255);
318 LocationBarViewGtk::LocationBarViewGtk(Browser
* browser
)
319 : OmniboxEditController(browser
->command_controller()->command_updater()),
320 LocationBar(browser
->profile()),
322 manage_passwords_icon_image_(NULL
),
326 site_type_alignment_(NULL
),
327 site_type_event_box_(NULL
),
328 location_icon_image_(NULL
),
330 enable_location_drag_(false),
331 security_info_label_(NULL
),
332 tab_to_search_alignment_(NULL
),
333 tab_to_search_box_(NULL
),
334 tab_to_search_full_label_(NULL
),
335 tab_to_search_partial_label_(NULL
),
336 tab_to_search_hint_(NULL
),
337 tab_to_search_hint_leading_label_(NULL
),
338 tab_to_search_hint_icon_(NULL
),
339 tab_to_search_hint_trailing_label_(NULL
),
341 popup_window_mode_(false),
342 theme_service_(NULL
),
345 show_selected_keyword_(false),
346 show_keyword_hint_(false),
347 weak_ptr_factory_(this) {
350 LocationBarViewGtk::~LocationBarViewGtk() {
351 // All of our widgets should be children of / owned by the alignment.
353 manage_passwords_icon_
.Destroy();
356 content_setting_hbox_
.Destroy();
357 page_action_hbox_
.Destroy();
360 void LocationBarViewGtk::Init(bool popup_window_mode
) {
361 popup_window_mode_
= popup_window_mode
;
363 theme_service_
= GtkThemeService::GetFrom(profile());
365 // Create the widget first, so we can pass it to the OmniboxViewGtk.
366 hbox_
.Own(gtk_hbox_new(FALSE
, kInnerPadding
));
367 gtk_container_set_border_width(GTK_CONTAINER(hbox_
.get()), kHboxBorder
);
368 // We will paint for the alignment, to paint the background and border.
369 gtk_widget_set_app_paintable(hbox_
.get(), TRUE
);
370 // Redraw the whole location bar when it changes size (e.g., when toggling
371 // the home button on/off.
372 gtk_widget_set_redraw_on_allocate(hbox_
.get(), TRUE
);
374 // Now initialize the OmniboxViewGtk.
375 omnibox_view_
.reset(new OmniboxViewGtk(this, browser_
, profile(),
377 popup_window_mode_
, hbox_
.get()));
378 omnibox_view_
->Init();
380 g_signal_connect(hbox_
.get(), "expose-event",
381 G_CALLBACK(&HandleExposeThunk
), this);
385 // Put |tab_to_search_box_|, |omnibox_view_|, and |tab_to_search_hint_| into
386 // a sub hbox, so that we can make this part horizontally shrinkable without
387 // affecting other elements in the location bar.
388 entry_box_
= gtk_hbox_new(FALSE
, kInnerPadding
);
389 gtk_widget_show(entry_box_
);
390 gtk_widget_set_size_request(entry_box_
, 0, -1);
391 gtk_box_pack_start(GTK_BOX(hbox_
.get()), entry_box_
, TRUE
, TRUE
, 0);
393 // We need to adjust the visibility of the search hint widgets according to
394 // the horizontal space in the |entry_box_|.
395 g_signal_connect(entry_box_
, "size-allocate",
396 G_CALLBACK(&OnEntryBoxSizeAllocateThunk
), this);
398 // Tab to search (the keyword box on the left hand side).
399 tab_to_search_full_label_
=
400 theme_service_
->BuildLabel(std::string(), ui::kGdkBlack
);
401 tab_to_search_partial_label_
=
402 theme_service_
->BuildLabel(std::string(), ui::kGdkBlack
);
403 GtkWidget
* tab_to_search_label_hbox
= gtk_hbox_new(FALSE
, 0);
404 gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox
),
405 tab_to_search_full_label_
, FALSE
, FALSE
, 0);
406 gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox
),
407 tab_to_search_partial_label_
, FALSE
, FALSE
, 0);
408 GtkWidget
* tab_to_search_hbox
= gtk_hbox_new(FALSE
, 0);
409 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
410 tab_to_search_magnifier_
= gtk_image_new_from_pixbuf(
411 rb
.GetNativeImageNamed(IDR_KEYWORD_SEARCH_MAGNIFIER
).ToGdkPixbuf());
412 gtk_box_pack_start(GTK_BOX(tab_to_search_hbox
), tab_to_search_magnifier_
,
414 gtk_util::CenterWidgetInHBox(tab_to_search_hbox
, tab_to_search_label_hbox
,
417 // This creates a box around the keyword text with a border, background color,
418 // and padding around the text.
419 tab_to_search_box_
= gtk_util::CreateGtkBorderBin(
420 tab_to_search_hbox
, NULL
, 1, 1, 1, 3);
421 gtk_widget_set_name(tab_to_search_box_
, "chrome-tab-to-search-box");
422 gtk_util::ActAsRoundedWindow(tab_to_search_box_
, kKeywordBorderColor
,
424 gtk_util::ROUNDED_ALL
, gtk_util::BORDER_ALL
);
426 // Put the event box in an alignment to get the padding correct.
427 tab_to_search_alignment_
= gtk_alignment_new(0, 0, 1, 1);
428 gtk_container_add(GTK_CONTAINER(tab_to_search_alignment_
),
430 gtk_box_pack_start(GTK_BOX(entry_box_
), tab_to_search_alignment_
,
433 // Show all children widgets of |tab_to_search_box_| initially, except
434 // |tab_to_search_partial_label_|.
435 gtk_widget_show_all(tab_to_search_box_
);
436 gtk_widget_hide(tab_to_search_partial_label_
);
438 omnibox_view_alignment_
= gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
439 gtk_container_add(GTK_CONTAINER(omnibox_view_alignment_
),
440 omnibox_view_
->GetNativeView());
441 gtk_box_pack_start(GTK_BOX(entry_box_
), omnibox_view_alignment_
,
444 // Tab to search notification (the hint on the right hand side).
445 tab_to_search_hint_
= gtk_hbox_new(FALSE
, 0);
446 gtk_widget_set_name(tab_to_search_hint_
, "chrome-tab-to-search-hint");
447 tab_to_search_hint_leading_label_
=
448 theme_service_
->BuildLabel(std::string(), kHintTextColor
);
449 gtk_widget_set_sensitive(tab_to_search_hint_leading_label_
, FALSE
);
450 tab_to_search_hint_icon_
= gtk_image_new_from_pixbuf(
451 rb
.GetNativeImageNamed(IDR_OMNIBOX_KEYWORD_HINT_TAB
).ToGdkPixbuf());
452 tab_to_search_hint_trailing_label_
=
453 theme_service_
->BuildLabel(std::string(), kHintTextColor
);
454 gtk_widget_set_sensitive(tab_to_search_hint_trailing_label_
, FALSE
);
455 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_
),
456 tab_to_search_hint_leading_label_
,
458 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_
),
459 tab_to_search_hint_icon_
,
461 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_
),
462 tab_to_search_hint_trailing_label_
,
464 // Show all children widgets of |tab_to_search_hint_| initially.
465 gtk_widget_show_all(tab_to_search_hint_
);
466 gtk_widget_hide(tab_to_search_hint_
);
467 // tab_to_search_hint_ gets hidden initially in OnChanged. Hiding it here
468 // doesn't work, someone is probably calling show_all on our parent box.
469 gtk_box_pack_end(GTK_BOX(entry_box_
), tab_to_search_hint_
, FALSE
, FALSE
, 0);
471 if (browser_defaults::bookmarks_enabled
&& !ShouldOnlyShowLocation()) {
472 // Hide the star icon in popups, app windows, etc.
474 gtk_box_pack_end(GTK_BOX(hbox_
.get()), star_
.get(), FALSE
, FALSE
, 0);
478 gtk_box_pack_end(GTK_BOX(hbox_
.get()), zoom_
.get(), FALSE
, FALSE
, 0);
480 CreateManagePasswordsIconButton();
481 gtk_box_pack_end(GTK_BOX(hbox_
.get()), manage_passwords_icon_
.get(), FALSE
,
484 content_setting_hbox_
.Own(gtk_hbox_new(FALSE
, kInnerPadding
+ 1));
485 gtk_widget_set_name(content_setting_hbox_
.get(),
486 "chrome-content-setting-hbox");
487 gtk_box_pack_end(GTK_BOX(hbox_
.get()), content_setting_hbox_
.get(),
490 for (int i
= 0; i
< CONTENT_SETTINGS_NUM_TYPES
; ++i
) {
491 ContentSettingImageViewGtk
* content_setting_view
=
492 new ContentSettingImageViewGtk(
493 static_cast<ContentSettingsType
>(i
), this);
494 content_setting_views_
.push_back(content_setting_view
);
495 gtk_box_pack_end(GTK_BOX(content_setting_hbox_
.get()),
496 content_setting_view
->widget(), FALSE
, FALSE
, 0);
499 page_action_hbox_
.Own(gtk_hbox_new(FALSE
, kInnerPadding
));
500 gtk_widget_set_name(page_action_hbox_
.get(),
501 "chrome-page-action-hbox");
502 gtk_box_pack_end(GTK_BOX(hbox_
.get()), page_action_hbox_
.get(),
505 // Now that we've created the widget hierarchy, connect to the main |hbox_|'s
506 // size-allocate so we can do proper resizing and eliding on
507 // |security_info_label_|.
508 g_signal_connect(hbox_
.get(), "size-allocate",
509 G_CALLBACK(&OnHboxSizeAllocateThunk
), this);
512 chrome::NOTIFICATION_BROWSER_THEME_CHANGED
,
513 content::Source
<ThemeService
>(theme_service_
));
515 chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED
,
516 content::Source
<Profile
>(profile()));
517 edit_bookmarks_enabled_
.Init(prefs::kEditBookmarksEnabled
,
518 profile()->GetPrefs(),
519 base::Bind(&LocationBarViewGtk::UpdateStarIcon
,
520 base::Unretained(this)));
522 theme_service_
->InitThemesFor(this);
525 void LocationBarViewGtk::SetPreviewEnabledPageAction(
526 ExtensionAction
* page_action
,
527 bool preview_enabled
) {
529 for (ScopedVector
<PageActionViewGtk
>::iterator iter
=
530 page_action_views_
.begin(); iter
!= page_action_views_
.end();
532 if ((*iter
)->page_action() == page_action
) {
533 (*iter
)->set_preview_enabled(preview_enabled
);
540 GtkWidget
* LocationBarViewGtk::GetPageActionWidget(
541 ExtensionAction
* page_action
) {
543 for (ScopedVector
<PageActionViewGtk
>::iterator iter
=
544 page_action_views_
.begin();
545 iter
!= page_action_views_
.end();
547 if ((*iter
)->page_action() == page_action
)
548 return (*iter
)->widget();
553 void LocationBarViewGtk::ShowStarBubble(const GURL
& url
,
554 bool newly_bookmarked
) {
559 BookmarkBubbleGtk::Show(star_
.get(), profile(), url
, newly_bookmarked
);
561 on_star_sized_
= base::Bind(&BookmarkBubbleGtk::Show
, star_
.get(),
562 profile(), url
, newly_bookmarked
);
566 void LocationBarViewGtk::ShowManagePasswordsBubble() {
567 if (GetToolbarModel()->input_in_progress() || !GetWebContents())
570 ManagePasswordsBubbleGtk::ShowBubble(GetWebContents());
573 void LocationBarViewGtk::ZoomChangedForActiveTab(bool can_show_bubble
) {
576 if (can_show_bubble
&& gtk_widget_get_visible(zoom_
.get()))
580 void LocationBarViewGtk::SetStarred(bool starred
) {
581 if (starred
== starred_
)
588 void LocationBarViewGtk::Update(const WebContents
* contents
) {
591 UpdateSiteTypeArea();
592 UpdateContentSettingsIcons();
595 omnibox_view_
->OnTabChanged(contents
);
597 omnibox_view_
->Update();
598 // The security level (background color) could have changed, etc.
599 if (theme_service_
->UsingNativeTheme()) {
600 // In GTK mode, we need our parent to redraw, as it draws the text entry
602 gtk_widget_queue_draw(gtk_widget_get_parent(widget()));
604 gtk_widget_queue_draw(widget());
606 ZoomBubbleGtk::CloseBubble();
609 void LocationBarViewGtk::OnChanged() {
610 UpdateSiteTypeArea();
612 const base::string16
keyword(omnibox_view_
->model()->keyword());
613 const bool is_keyword_hint
= omnibox_view_
->model()->is_keyword_hint();
614 show_selected_keyword_
= !keyword
.empty() && !is_keyword_hint
;
615 show_keyword_hint_
= !keyword
.empty() && is_keyword_hint
;
617 if (show_selected_keyword_
)
618 SetKeywordLabel(keyword
);
620 if (show_keyword_hint_
)
621 SetKeywordHintLabel(keyword
);
623 AdjustChildrenVisibility();
626 void LocationBarViewGtk::OnSetFocus() {
627 AccessibilityTextBoxInfo
info(profile(),
628 l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION
),
629 std::string(), false);
630 ExtensionAccessibilityEventRouter::GetInstance()->HandleControlEvent(
631 ui::AccessibilityTypes::EVENT_FOCUS
, &info
);
633 // Update the keyword and search hint states.
637 InstantController
* LocationBarViewGtk::GetInstant() {
638 return browser_
->instant_controller() ?
639 browser_
->instant_controller()->instant() : NULL
;
642 WebContents
* LocationBarViewGtk::GetWebContents() {
643 return browser_
->tab_strip_model()->GetActiveWebContents();
646 ToolbarModel
* LocationBarViewGtk::GetToolbarModel() {
647 return browser_
->toolbar_model();
650 const ToolbarModel
* LocationBarViewGtk::GetToolbarModel() const {
651 return browser_
->toolbar_model();
654 void LocationBarViewGtk::ShowFirstRunBubble() {
655 // We need the browser window to be shown before we can show the bubble, but
656 // we get called before that's happened.
657 base::MessageLoop::current()->PostTask(
659 base::Bind(&LocationBarViewGtk::ShowFirstRunBubbleInternal
,
660 weak_ptr_factory_
.GetWeakPtr()));
663 GURL
LocationBarViewGtk::GetDestinationURL() const {
664 return destination_url();
667 WindowOpenDisposition
LocationBarViewGtk::GetWindowOpenDisposition() const {
668 return disposition();
671 content::PageTransition
LocationBarViewGtk::GetPageTransition() const {
675 void LocationBarViewGtk::AcceptInput() {
676 omnibox_view_
->model()->AcceptInput(CURRENT_TAB
, false);
679 void LocationBarViewGtk::FocusLocation(bool select_all
) {
680 omnibox_view_
->SetFocus();
682 omnibox_view_
->SelectAll(true);
685 void LocationBarViewGtk::FocusSearch() {
686 omnibox_view_
->SetFocus();
687 omnibox_view_
->SetForcedQuery();
690 void LocationBarViewGtk::UpdateContentSettingsIcons() {
691 bool any_visible
= false;
692 for (ScopedVector
<PageToolViewGtk
>::iterator
i(
693 content_setting_views_
.begin());
694 i
!= content_setting_views_
.end(); ++i
) {
695 (*i
)->Update(GetToolbarModel()->input_in_progress() ?
696 NULL
: GetWebContents());
697 any_visible
= (*i
)->IsVisible() || any_visible
;
699 // If there are no visible content things, hide the top level box so it
700 // doesn't mess with padding.
701 gtk_widget_set_visible(content_setting_hbox_
.get(), any_visible
);
704 void LocationBarViewGtk::UpdateManagePasswordsIconAndBubble() {
705 UpdateManagePasswordsIcon();
708 void LocationBarViewGtk::UpdatePageActions() {
709 std::vector
<ExtensionAction
*> new_page_actions
;
711 WebContents
* contents
= GetWebContents();
713 LocationBarController
* location_bar_controller
=
714 extensions::TabHelper::FromWebContents(contents
)->
715 location_bar_controller();
716 new_page_actions
= location_bar_controller
->GetCurrentActions();
719 // Initialize on the first call, or re-initialize if more extensions have been
720 // loaded or added after startup.
721 if (new_page_actions
!= page_actions_
) {
722 page_actions_
.swap(new_page_actions
);
723 page_action_views_
.clear();
725 for (size_t i
= 0; i
< page_actions_
.size(); ++i
) {
726 page_action_views_
.push_back(
727 new PageActionViewGtk(this, page_actions_
[i
]));
728 gtk_box_pack_end(GTK_BOX(page_action_hbox_
.get()),
729 page_action_views_
[i
]->widget(), FALSE
, FALSE
, 0);
731 content::NotificationService::current()->Notify(
732 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED
,
733 content::Source
<LocationBar
>(this),
734 content::NotificationService::NoDetails());
737 if (!page_action_views_
.empty() && contents
) {
738 GURL url
= GetWebContents()->GetURL();
740 for (size_t i
= 0; i
< page_action_views_
.size(); i
++) {
741 page_action_views_
[i
]->UpdateVisibility(
742 GetToolbarModel()->input_in_progress() ? NULL
: contents
, url
);
744 gtk_widget_queue_draw(hbox_
.get());
747 // If there are no visible page actions, hide the hbox too, so that it does
748 // not affect the padding in the location bar.
749 gtk_widget_set_visible(page_action_hbox_
.get(),
750 PageActionVisibleCount() && !ShouldOnlyShowLocation());
753 void LocationBarViewGtk::InvalidatePageActions() {
754 size_t count_before
= page_action_views_
.size();
755 page_action_views_
.clear();
756 if (page_action_views_
.size() != count_before
) {
757 content::NotificationService::current()->Notify(
758 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED
,
759 content::Source
<LocationBar
>(this),
760 content::NotificationService::NoDetails());
764 void LocationBarViewGtk::UpdateOpenPDFInReaderPrompt() {
765 // Not implemented on Gtk.
768 void LocationBarViewGtk::UpdateGeneratedCreditCardView() {
772 void LocationBarViewGtk::SaveStateToContents(WebContents
* contents
) {
773 omnibox_view_
->SaveStateToTab(contents
);
776 void LocationBarViewGtk::Revert() {
777 omnibox_view_
->RevertAll();
780 const OmniboxView
* LocationBarViewGtk::GetOmniboxView() const {
781 return omnibox_view_
.get();
784 OmniboxView
* LocationBarViewGtk::GetOmniboxView() {
785 return omnibox_view_
.get();
788 LocationBarTesting
* LocationBarViewGtk::GetLocationBarForTesting() {
792 int LocationBarViewGtk::PageActionCount() {
793 return page_action_views_
.size();
796 int LocationBarViewGtk::PageActionVisibleCount() {
798 gtk_container_foreach(GTK_CONTAINER(page_action_hbox_
.get()),
799 CountVisibleWidgets
, &count
);
803 ExtensionAction
* LocationBarViewGtk::GetPageAction(size_t index
) {
804 if (index
>= page_action_views_
.size()) {
809 return page_action_views_
[index
]->page_action();
812 ExtensionAction
* LocationBarViewGtk::GetVisiblePageAction(size_t index
) {
813 size_t visible_index
= 0;
814 for (size_t i
= 0; i
< page_action_views_
.size(); ++i
) {
815 if (page_action_views_
[i
]->IsVisible()) {
816 if (index
== visible_index
++)
817 return page_action_views_
[i
]->page_action();
825 void LocationBarViewGtk::TestPageActionPressed(size_t index
) {
826 if (index
>= page_action_views_
.size()) {
831 page_action_views_
[index
]->TestActivatePageAction();
834 bool LocationBarViewGtk::GetBookmarkStarVisibility() {
838 void LocationBarViewGtk::Observe(int type
,
839 const content::NotificationSource
& source
,
840 const content::NotificationDetails
& details
) {
842 case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED
: {
843 // Only update if the updated action box was for the active tab contents.
844 WebContents
* target_tab
= content::Details
<WebContents
>(details
).ptr();
845 if (target_tab
== GetWebContents())
850 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED
: {
851 if (theme_service_
->UsingNativeTheme()) {
852 gtk_widget_modify_bg(tab_to_search_box_
, GTK_STATE_NORMAL
, NULL
);
854 GdkColor border_color
= theme_service_
->GetGdkColor(
855 ThemeProperties::COLOR_FRAME
);
856 gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_
, border_color
);
858 gtk_util::UndoForceFontSize(security_info_label_
);
859 gtk_util::UndoForceFontSize(tab_to_search_full_label_
);
860 gtk_util::UndoForceFontSize(tab_to_search_partial_label_
);
861 gtk_util::UndoForceFontSize(tab_to_search_hint_leading_label_
);
862 gtk_util::UndoForceFontSize(tab_to_search_hint_trailing_label_
);
864 gtk_alignment_set_padding(GTK_ALIGNMENT(omnibox_view_alignment_
),
866 gtk_alignment_set_padding(GTK_ALIGNMENT(tab_to_search_alignment_
),
868 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_
),
871 gtk_widget_modify_bg(tab_to_search_box_
, GTK_STATE_NORMAL
,
872 &kKeywordBackgroundColor
);
873 gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_
,
874 kKeywordBorderColor
);
876 // Until we switch to vector graphics, force the font size of labels.
877 // 12.1px = 9pt @ 96dpi
878 gtk_util::ForceFontSizePixels(security_info_label_
, 12.1);
879 gtk_util::ForceFontSizePixels(tab_to_search_full_label_
,
880 browser_defaults::kOmniboxFontPixelSize
);
881 gtk_util::ForceFontSizePixels(tab_to_search_partial_label_
,
882 browser_defaults::kOmniboxFontPixelSize
);
883 gtk_util::ForceFontSizePixels(tab_to_search_hint_leading_label_
,
884 browser_defaults::kOmniboxFontPixelSize
);
885 gtk_util::ForceFontSizePixels(tab_to_search_hint_trailing_label_
,
886 browser_defaults::kOmniboxFontPixelSize
);
888 const int left_right
= popup_window_mode_
? kPopupEdgeThickness
: 0;
889 gtk_alignment_set_padding(GTK_ALIGNMENT(omnibox_view_alignment_
),
890 kBorderThickness
, kBorderThickness
,
891 left_right
, left_right
);
892 gtk_alignment_set_padding(GTK_ALIGNMENT(tab_to_search_alignment_
),
894 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_
),
899 UpdateManagePasswordsIcon();
901 UpdateSiteTypeArea();
902 UpdateContentSettingsIcons();
911 void LocationBarViewGtk::BuildSiteTypeArea() {
912 location_icon_image_
= gtk_image_new();
913 gtk_widget_set_name(location_icon_image_
, "chrome-location-icon");
915 GtkWidget
* icon_alignment
= gtk_alignment_new(0, 0, 1, 1);
916 gtk_alignment_set_padding(GTK_ALIGNMENT(icon_alignment
), 0, 0, 2, 0);
917 gtk_container_add(GTK_CONTAINER(icon_alignment
), location_icon_image_
);
918 gtk_widget_show_all(icon_alignment
);
920 security_info_label_
= gtk_label_new(NULL
);
921 gtk_label_set_ellipsize(GTK_LABEL(security_info_label_
),
922 PANGO_ELLIPSIZE_MIDDLE
);
923 gtk_widget_modify_fg(GTK_WIDGET(security_info_label_
), GTK_STATE_NORMAL
,
924 &kEvSecureTextColor
);
925 gtk_widget_set_name(security_info_label_
,
926 "chrome-location-bar-security-info-label");
928 GtkWidget
* site_type_hbox
= gtk_hbox_new(FALSE
, 1);
929 gtk_box_pack_start(GTK_BOX(site_type_hbox
), icon_alignment
,
931 gtk_box_pack_start(GTK_BOX(site_type_hbox
), security_info_label_
,
934 site_type_event_box_
= gtk_event_box_new();
935 gtk_widget_modify_bg(site_type_event_box_
, GTK_STATE_NORMAL
,
936 &kEvSecureBackgroundColor
);
937 g_signal_connect(site_type_event_box_
, "drag-data-get",
938 G_CALLBACK(&OnIconDragDataThunk
), this);
939 g_signal_connect(site_type_event_box_
, "drag-begin",
940 G_CALLBACK(&OnIconDragBeginThunk
), this);
941 g_signal_connect(site_type_event_box_
, "drag-end",
942 G_CALLBACK(&OnIconDragEndThunk
), this);
944 // Make the event box not visible so it does not paint a background.
945 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_
),
947 gtk_widget_set_name(site_type_event_box_
,
948 "chrome-location-icon-eventbox");
949 gtk_container_add(GTK_CONTAINER(site_type_event_box_
),
952 // Put the event box in an alignment to get the padding correct.
953 site_type_alignment_
= gtk_alignment_new(0, 0, 1, 1);
954 gtk_container_add(GTK_CONTAINER(site_type_alignment_
),
955 site_type_event_box_
);
956 gtk_box_pack_start(GTK_BOX(hbox_
.get()), site_type_alignment_
,
959 gtk_widget_set_tooltip_text(location_icon_image_
,
960 l10n_util::GetStringUTF8(IDS_TOOLTIP_LOCATION_ICON
).c_str());
962 g_signal_connect(site_type_event_box_
, "button-release-event",
963 G_CALLBACK(&OnIconReleasedThunk
), this);
966 void LocationBarViewGtk::SetSiteTypeDragSource() {
967 bool enable
= !GetOmniboxView()->IsEditingOrEmpty();
968 if (enable_location_drag_
== enable
)
970 enable_location_drag_
= enable
;
973 gtk_drag_source_unset(site_type_event_box_
);
977 gtk_drag_source_set(site_type_event_box_
, GDK_BUTTON1_MASK
,
978 NULL
, 0, GDK_ACTION_COPY
);
979 ui::SetSourceTargetListFromCodeMask(site_type_event_box_
,
982 ui::CHROME_NAMED_URL
);
985 gboolean
LocationBarViewGtk::HandleExpose(GtkWidget
* widget
,
986 GdkEventExpose
* event
) {
987 // If we're not using GTK theming, draw our own border over the edge pixels
988 // of the background.
989 GtkThemeService
* theme_service
= GtkThemeService::GetFrom(profile());
990 if (!theme_service
->UsingNativeTheme()) {
991 // Perform a scoped paint to fill in the background color.
993 gfx::CanvasSkiaPaint
canvas(event
, /*opaque=*/false);
995 GtkAllocation allocation
;
996 gtk_widget_get_allocation(widget
, &allocation
);
998 int thickness
= popup_window_mode_
?
999 kPopupEdgeThickness
: kNormalEdgeThickness
;
1000 gfx::Rect
bounds(allocation
);
1001 bounds
.Inset(thickness
, thickness
);
1003 const SkColor color
= SK_ColorWHITE
;
1004 if (popup_window_mode_
) {
1005 canvas
.FillRect(bounds
, color
);
1008 paint
.setStyle(SkPaint::kFill_Style
);
1009 paint
.setColor(color
);
1010 const int kBorderCornerRadius
= 2;
1011 canvas
.DrawRoundRect(bounds
, kBorderCornerRadius
, paint
);
1015 if (popup_window_mode_
) {
1016 NineBox(IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_LEFT
,
1017 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP
,
1018 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_RIGHT
,
1019 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_LEFT
,
1020 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_CENTER
,
1021 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_RIGHT
,
1022 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM_LEFT
,
1023 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM
,
1024 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM_RIGHT
).
1025 RenderToWidget(widget
);
1027 NineBox(IDR_OMNIBOX_BORDER_AND_SHADOW_TOP_LEFT
,
1028 IDR_OMNIBOX_BORDER_AND_SHADOW_TOP
,
1029 IDR_OMNIBOX_BORDER_AND_SHADOW_TOP_RIGHT
,
1030 IDR_OMNIBOX_BORDER_AND_SHADOW_LEFT
,
1031 IDR_OMNIBOX_BORDER_AND_SHADOW_CENTER
,
1032 IDR_OMNIBOX_BORDER_AND_SHADOW_RIGHT
,
1033 IDR_OMNIBOX_BORDER_AND_SHADOW_BOTTOM_LEFT
,
1034 IDR_OMNIBOX_BORDER_AND_SHADOW_BOTTOM
,
1035 IDR_OMNIBOX_BORDER_AND_SHADOW_BOTTOM_RIGHT
).
1036 RenderToWidget(widget
);
1040 return FALSE
; // Continue propagating the expose.
1043 gboolean
LocationBarViewGtk::OnIconReleased(GtkWidget
* sender
,
1044 GdkEventButton
* event
) {
1045 WebContents
* tab
= GetWebContents();
1047 if (event
->button
== 1) {
1048 // Do not show page info if the user has been editing the location
1049 // bar, or the location bar is at the NTP.
1050 if (GetOmniboxView()->IsEditingOrEmpty())
1053 // (0,0) event coordinates indicates that the release came at the end of
1055 if (event
->x
== 0 && event
->y
== 0)
1058 // Important to use GetVisibleEntry to match what's showing in the omnibox.
1059 NavigationEntry
* nav_entry
= tab
->GetController().GetVisibleEntry();
1064 chrome::ShowWebsiteSettings(browser_
, tab
, nav_entry
->GetURL(),
1065 nav_entry
->GetSSL());
1067 } else if (event
->button
== 2) {
1068 // When the user middle clicks on the location icon, try to open the
1069 // contents of the PRIMARY selection in the current tab.
1070 // If the click was outside our bounds, do nothing.
1071 if (!gtk_util::WidgetBounds(sender
).Contains(
1072 gfx::Point(event
->x
, event
->y
))) {
1077 if (!gtk_util::URLFromPrimarySelection(profile(), &url
))
1080 tab
->OpenURL(OpenURLParams(
1081 url
, content::Referrer(), CURRENT_TAB
, content::PAGE_TRANSITION_TYPED
,
1089 void LocationBarViewGtk::OnIconDragData(GtkWidget
* sender
,
1090 GdkDragContext
* context
,
1091 GtkSelectionData
* data
,
1092 guint info
, guint time
) {
1093 ui::WriteURLWithName(data
, drag_url_
, drag_title_
, info
);
1096 void LocationBarViewGtk::OnIconDragBegin(GtkWidget
* sender
,
1097 GdkDragContext
* context
) {
1098 content::WebContents
* web_contents
= GetWebContents();
1099 gfx::Image favicon
=
1100 FaviconTabHelper::FromWebContents(web_contents
)->GetFavicon();
1101 if (favicon
.IsEmpty())
1103 drag_url_
= web_contents
->GetURL();
1104 drag_title_
= web_contents
->GetTitle();
1105 drag_icon_
= GetDragRepresentation(favicon
.ToGdkPixbuf(), drag_title_
,
1107 gtk_drag_set_icon_widget(context
, drag_icon_
, 0, 0);
1110 void LocationBarViewGtk::OnIconDragEnd(GtkWidget
* sender
,
1111 GdkDragContext
* context
) {
1113 gtk_widget_destroy(drag_icon_
);
1115 drag_url_
= GURL::EmptyGURL();
1116 drag_title_
.clear();
1119 void LocationBarViewGtk::OnHboxSizeAllocate(GtkWidget
* sender
,
1120 GtkAllocation
* allocation
) {
1121 if (hbox_width_
!= allocation
->width
) {
1122 hbox_width_
= allocation
->width
;
1123 UpdateEVCertificateLabelSize();
1125 InstantService
* instant_service
=
1126 InstantServiceFactory::GetForProfile(profile());
1127 if (instant_service
) {
1128 instant_service
->OnOmniboxStartMarginChanged(
1129 AllocationToRect(*allocation
).x());
1133 void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkWidget
* sender
,
1134 GtkAllocation
* allocation
) {
1135 if (entry_box_width_
!= allocation
->width
) {
1136 entry_box_width_
= allocation
->width
;
1137 AdjustChildrenVisibility();
1141 gboolean
LocationBarViewGtk::OnZoomButtonPress(GtkWidget
* widget
,
1142 GdkEventButton
* event
) {
1143 if (event
->button
== 1 && GetWebContents()) {
1144 // If the zoom icon is clicked, show the zoom bubble and keep it open until
1146 ZoomBubbleGtk::ShowBubble(GetWebContents(), false);
1152 gboolean
LocationBarViewGtk::OnManagePasswordsIconButtonPress(
1153 GtkWidget
* widget
, GdkEventButton
* event
) {
1154 if (event
->button
== 1 && GetWebContents()) {
1155 // If the manage passwords icon is clicked, show the manage passwords bubble
1156 // and keep it open until the user makes a choice or clicks outside the
1158 ManagePasswordsBubbleGtk::ShowBubble(GetWebContents());
1164 void LocationBarViewGtk::OnStarButtonSizeAllocate(GtkWidget
* sender
,
1165 GtkAllocation
* allocation
) {
1166 if (!on_star_sized_
.is_null()) {
1167 on_star_sized_
.Run();
1168 on_star_sized_
.Reset();
1173 gboolean
LocationBarViewGtk::OnStarButtonPress(GtkWidget
* widget
,
1174 GdkEventButton
* event
) {
1175 if (event
->button
!= 1)
1177 chrome::ExecuteCommand(browser_
, IDC_BOOKMARK_PAGE_FROM_STAR
);
1181 void LocationBarViewGtk::UpdateSiteTypeArea() {
1182 // The icon is always visible except when the |tab_to_search_alignment_| is
1184 if (!omnibox_view_
->model()->keyword().empty() &&
1185 !omnibox_view_
->model()->is_keyword_hint()) {
1186 gtk_widget_hide(site_type_area());
1190 int resource_id
= omnibox_view_
->GetIcon();
1191 gtk_image_set_from_pixbuf(
1192 GTK_IMAGE(location_icon_image_
),
1193 theme_service_
->GetImageNamed(resource_id
).ToGdkPixbuf());
1195 if (GetToolbarModel()->GetSecurityLevel(false) == ToolbarModel::EV_SECURE
) {
1196 if (!gtk_util::IsActingAsRoundedWindow(site_type_event_box_
)) {
1197 // Fun fact: If wee try to make |site_type_event_box_| act as a
1198 // rounded window while it doesn't have a visible window, GTK interprets
1199 // this as a sign that it should paint the skyline texture into the
1201 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_
),
1204 gtk_util::ActAsRoundedWindow(site_type_event_box_
,
1205 kEvSecureBorderColor
,
1207 gtk_util::ROUNDED_ALL
,
1208 gtk_util::BORDER_ALL
);
1211 base::string16 info_text
= GetToolbarModel()->GetEVCertName();
1212 gtk_label_set_text(GTK_LABEL(security_info_label_
),
1213 base::UTF16ToUTF8(info_text
).c_str());
1215 UpdateEVCertificateLabelSize();
1217 gtk_widget_show(GTK_WIDGET(security_info_label_
));
1219 if (gtk_util::IsActingAsRoundedWindow(site_type_event_box_
)) {
1220 gtk_util::StopActingAsRoundedWindow(site_type_event_box_
);
1222 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_
),
1226 gtk_widget_hide(GTK_WIDGET(security_info_label_
));
1229 if (GetOmniboxView()->IsEditingOrEmpty()) {
1230 // Do not show the tooltip if the user has been editing the location
1231 // bar, or the location bar is at the NTP.
1232 gtk_widget_set_tooltip_text(location_icon_image_
, "");
1234 gtk_widget_set_tooltip_text(location_icon_image_
,
1235 l10n_util::GetStringUTF8(IDS_TOOLTIP_LOCATION_ICON
).c_str());
1238 gtk_widget_show(site_type_area());
1240 SetSiteTypeDragSource();
1243 void LocationBarViewGtk::UpdateEVCertificateLabelSize() {
1244 // Figure out the width of the average character.
1245 PangoLayout
* layout
= gtk_label_get_layout(GTK_LABEL(security_info_label_
));
1246 PangoContext
* context
= pango_layout_get_context(layout
);
1247 PangoFontMetrics
* metrics
= pango_context_get_metrics(
1249 gtk_widget_get_style(security_info_label_
)->font_desc
,
1250 pango_context_get_language(context
));
1252 pango_font_metrics_get_approximate_char_width(metrics
) / PANGO_SCALE
;
1254 // The EV label should never take up more than half the hbox. We try to
1255 // correct our inaccurate measurement units ("the average character width")
1256 // by dividing more than an even 2.
1257 GtkAllocation security_label_allocation
;
1258 gtk_widget_get_allocation(security_info_label_
, &security_label_allocation
);
1259 GtkAllocation entry_box_allocation
;
1260 gtk_widget_get_allocation(entry_box_
, &entry_box_allocation
);
1261 int text_area
= security_label_allocation
.width
+
1262 entry_box_allocation
.width
;
1263 int max_chars
= static_cast<int>(static_cast<float>(text_area
) /
1264 static_cast<float>(char_width
) / 2.75);
1265 // Don't let the label be smaller than 10 characters so that the country
1266 // code is always visible.
1267 gtk_label_set_max_width_chars(GTK_LABEL(security_info_label_
),
1268 std::max(10, max_chars
));
1270 pango_font_metrics_unref(metrics
);
1273 void LocationBarViewGtk::SetKeywordLabel(const base::string16
& keyword
) {
1274 if (keyword
.empty())
1277 TemplateURLService
* template_url_service
=
1278 TemplateURLServiceFactory::GetForProfile(profile());
1279 if (!template_url_service
)
1282 bool is_extension_keyword
;
1283 const base::string16 short_name
= template_url_service
->GetKeywordShortName(
1284 keyword
, &is_extension_keyword
);
1285 const base::string16 min_string
=
1286 location_bar_util::CalculateMinString(short_name
);
1287 const base::string16 full_name
= is_extension_keyword
?
1289 l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT
, short_name
);
1290 const base::string16 partial_name
= is_extension_keyword
?
1292 l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT
, min_string
);
1293 gtk_label_set_text(GTK_LABEL(tab_to_search_full_label_
),
1294 base::UTF16ToUTF8(full_name
).c_str());
1295 gtk_label_set_text(GTK_LABEL(tab_to_search_partial_label_
),
1296 base::UTF16ToUTF8(partial_name
).c_str());
1298 if (last_keyword_
!= keyword
) {
1299 last_keyword_
= keyword
;
1301 if (is_extension_keyword
) {
1302 const TemplateURL
* template_url
=
1303 template_url_service
->GetTemplateURLForKeyword(keyword
);
1304 gfx::Image image
= extensions::OmniboxAPI::Get(profile())->
1305 GetOmniboxIcon(template_url
->GetExtensionId());
1306 gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_
),
1307 image
.ToGdkPixbuf());
1309 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
1310 gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_
),
1311 rb
.GetNativeImageNamed(IDR_OMNIBOX_SEARCH
).ToGdkPixbuf());
1316 void LocationBarViewGtk::SetKeywordHintLabel(const base::string16
& keyword
) {
1317 if (keyword
.empty())
1320 TemplateURLService
* template_url_service
=
1321 TemplateURLServiceFactory::GetForProfile(profile());
1322 if (!template_url_service
)
1325 bool is_extension_keyword
;
1326 const base::string16 short_name
= template_url_service
->
1327 GetKeywordShortName(keyword
, &is_extension_keyword
);
1328 int message_id
= is_extension_keyword
?
1329 IDS_OMNIBOX_EXTENSION_KEYWORD_HINT
: IDS_OMNIBOX_KEYWORD_HINT
;
1330 std::vector
<size_t> content_param_offsets
;
1331 const base::string16 keyword_hint
= l10n_util::GetStringFUTF16(
1335 &content_param_offsets
);
1336 if (content_param_offsets
.size() != 2) {
1337 // See comments on an identical NOTREACHED() in search_provider.cc.
1342 std::string
leading(base::UTF16ToUTF8(
1343 keyword_hint
.substr(0, content_param_offsets
.front())));
1344 std::string
trailing(base::UTF16ToUTF8(
1345 keyword_hint
.substr(content_param_offsets
.front())));
1346 gtk_label_set_text(GTK_LABEL(tab_to_search_hint_leading_label_
),
1348 gtk_label_set_text(GTK_LABEL(tab_to_search_hint_trailing_label_
),
1352 void LocationBarViewGtk::ShowFirstRunBubbleInternal() {
1353 if (!omnibox_view_
.get() || !gtk_widget_get_window(widget()))
1356 gfx::Rect bounds
= gtk_util::WidgetBounds(location_icon_image_
);
1357 bounds
.set_x(bounds
.x() + kFirstRunBubbleLeftSpacing
);
1358 FirstRunBubble::Show(browser_
, location_icon_image_
, bounds
);
1361 void LocationBarViewGtk::ShowZoomBubble() {
1362 if (GetToolbarModel()->input_in_progress() || !GetWebContents())
1365 ZoomBubbleGtk::ShowBubble(GetWebContents(), true);
1368 void LocationBarViewGtk::AdjustChildrenVisibility() {
1369 int text_width
= omnibox_view_
->GetTextWidth();
1370 int available_width
= entry_box_width_
- text_width
- kInnerPadding
;
1372 // Only one of |tab_to_search_alignment_| and |tab_to_search_hint_| can be
1373 // visible at the same time.
1374 if (!show_selected_keyword_
&&
1375 gtk_widget_get_visible(tab_to_search_alignment_
)) {
1376 gtk_widget_hide(tab_to_search_alignment_
);
1377 } else if (!show_keyword_hint_
&&
1378 gtk_widget_get_visible(tab_to_search_hint_
)) {
1379 gtk_widget_hide(tab_to_search_hint_
);
1382 if (show_selected_keyword_
) {
1383 GtkRequisition box
, full_label
, partial_label
;
1384 gtk_widget_size_request(tab_to_search_box_
, &box
);
1385 gtk_widget_size_request(tab_to_search_full_label_
, &full_label
);
1386 gtk_widget_size_request(tab_to_search_partial_label_
, &partial_label
);
1387 int full_partial_width_diff
= full_label
.width
- partial_label
.width
;
1389 int partial_box_width
;
1390 if (gtk_widget_get_visible(tab_to_search_full_label_
)) {
1391 full_box_width
= box
.width
;
1392 partial_box_width
= full_box_width
- full_partial_width_diff
;
1394 partial_box_width
= box
.width
;
1395 full_box_width
= partial_box_width
+ full_partial_width_diff
;
1398 if (partial_box_width
>= entry_box_width_
- kInnerPadding
) {
1399 gtk_widget_hide(tab_to_search_alignment_
);
1400 } else if (full_box_width
>= available_width
) {
1401 gtk_widget_hide(tab_to_search_full_label_
);
1402 gtk_widget_show(tab_to_search_partial_label_
);
1403 gtk_widget_show(tab_to_search_alignment_
);
1404 } else if (full_box_width
< available_width
) {
1405 gtk_widget_hide(tab_to_search_partial_label_
);
1406 gtk_widget_show(tab_to_search_full_label_
);
1407 gtk_widget_show(tab_to_search_alignment_
);
1409 } else if (show_keyword_hint_
) {
1410 GtkRequisition leading
, icon
, trailing
;
1411 gtk_widget_size_request(tab_to_search_hint_leading_label_
, &leading
);
1412 gtk_widget_size_request(tab_to_search_hint_icon_
, &icon
);
1413 gtk_widget_size_request(tab_to_search_hint_trailing_label_
, &trailing
);
1414 int full_width
= leading
.width
+ icon
.width
+ trailing
.width
;
1416 if (icon
.width
>= entry_box_width_
- kInnerPadding
) {
1417 gtk_widget_hide(tab_to_search_hint_
);
1418 } else if (full_width
>= available_width
) {
1419 gtk_widget_hide(tab_to_search_hint_leading_label_
);
1420 gtk_widget_hide(tab_to_search_hint_trailing_label_
);
1421 gtk_widget_show(tab_to_search_hint_
);
1422 } else if (full_width
< available_width
) {
1423 gtk_widget_show(tab_to_search_hint_leading_label_
);
1424 gtk_widget_show(tab_to_search_hint_trailing_label_
);
1425 gtk_widget_show(tab_to_search_hint_
);
1430 GtkWidget
* LocationBarViewGtk::CreateIconButton(
1435 gboolean (click_callback
)(GtkWidget
*, GdkEventButton
*, gpointer
)) {
1437 gtk_image_new_from_pixbuf(
1438 theme_service_
->GetImageNamed(image_id
).ToGdkPixbuf()) :
1441 GtkWidget
* alignment
= gtk_alignment_new(0, 0, 1, 1);
1442 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment
), 0, 0,
1444 gtk_container_add(GTK_CONTAINER(alignment
), *image
);
1446 GtkWidget
* result
= gtk_event_box_new();
1447 gtk_event_box_set_visible_window(GTK_EVENT_BOX(result
), FALSE
);
1448 gtk_container_add(GTK_CONTAINER(result
), alignment
);
1449 gtk_widget_show_all(result
);
1451 if (debug_id
!= VIEW_ID_NONE
)
1452 ViewIDUtil::SetID(result
, debug_id
);
1455 gtk_widget_set_tooltip_text(result
,
1456 l10n_util::GetStringUTF8(tooltip_id
).c_str());
1459 g_signal_connect(result
, "button-press-event",
1460 G_CALLBACK(click_callback
), this);
1465 void LocationBarViewGtk::CreateZoomButton() {
1466 zoom_
.Own(CreateIconButton(&zoom_image_
,
1468 VIEW_ID_ZOOM_BUTTON
,
1470 OnZoomButtonPressThunk
));
1473 void LocationBarViewGtk::CreateManagePasswordsIconButton() {
1474 manage_passwords_icon_
.Own(CreateIconButton(
1475 &manage_passwords_icon_image_
, 0, VIEW_ID_MANAGE_PASSWORDS_ICON_BUTTON
, 0,
1476 OnManagePasswordsIconButtonPressThunk
));
1479 void LocationBarViewGtk::CreateStarButton() {
1480 star_
.Own(CreateIconButton(&star_image_
,
1482 VIEW_ID_STAR_BUTTON
,
1484 OnStarButtonPressThunk
));
1485 // We need to track when the star button is resized to show any bubble
1486 // attached to it at this time.
1487 g_signal_connect(star_image_
, "size-allocate",
1488 G_CALLBACK(&OnStarButtonSizeAllocateThunk
), this);
1491 void LocationBarViewGtk::UpdateZoomIcon() {
1492 WebContents
* web_contents
= GetWebContents();
1493 if (!zoom_
.get() || !web_contents
)
1496 ZoomController
* zoom_controller
=
1497 ZoomController::FromWebContents(web_contents
);
1498 if (!zoom_controller
|| zoom_controller
->IsAtDefaultZoom() ||
1499 GetToolbarModel()->input_in_progress()) {
1500 gtk_widget_hide(zoom_
.get());
1501 ZoomBubbleGtk::CloseBubble();
1505 const int zoom_resource
= zoom_controller
->GetResourceForZoomLevel();
1506 gtk_image_set_from_pixbuf(GTK_IMAGE(zoom_image_
),
1507 theme_service_
->GetImageNamed(zoom_resource
).ToGdkPixbuf());
1509 base::string16 tooltip
= l10n_util::GetStringFUTF16Int(
1510 IDS_TOOLTIP_ZOOM
, zoom_controller
->zoom_percent());
1511 gtk_widget_set_tooltip_text(zoom_
.get(), base::UTF16ToUTF8(tooltip
).c_str());
1513 gtk_widget_show(zoom_
.get());
1516 void LocationBarViewGtk::UpdateManagePasswordsIcon() {
1517 WebContents
* web_contents
= GetWebContents();
1518 if (!manage_passwords_icon_
.get() || !web_contents
)
1521 ManagePasswordsBubbleUIController
* manage_passwords_bubble_ui_controller
=
1522 ManagePasswordsBubbleUIController::FromWebContents(web_contents
);
1523 if (!manage_passwords_bubble_ui_controller
||
1524 !manage_passwords_bubble_ui_controller
->password_to_be_saved() ||
1525 GetToolbarModel()->input_in_progress()) {
1526 gtk_widget_hide(manage_passwords_icon_
.get());
1527 ManagePasswordsBubbleGtk::CloseBubble();
1531 gtk_image_set_from_pixbuf(
1532 GTK_IMAGE(manage_passwords_icon_image_
),
1533 theme_service_
->GetImageNamed(IDR_SAVE_PASSWORD
).ToGdkPixbuf());
1535 base::string16 tooltip
=
1536 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TOOLTIP_SAVE
);
1537 gtk_widget_set_tooltip_text(manage_passwords_icon_
.get(),
1538 base::UTF16ToUTF8(tooltip
).c_str());
1540 gtk_widget_show(manage_passwords_icon_
.get());
1541 if (manage_passwords_bubble_ui_controller
->
1542 manage_passwords_bubble_needs_showing()) {
1543 ShowManagePasswordsBubble();
1544 manage_passwords_bubble_ui_controller
->OnBubbleShown();
1548 void LocationBarViewGtk::UpdateStarIcon() {
1551 // Indicate the star icon is not correctly sized. It will be marked as sized
1552 // when the next size-allocate signal is received by the star widget.
1553 star_sized_
= false;
1554 if (browser_defaults::bookmarks_enabled
&& !popup_window_mode_
&&
1555 !GetToolbarModel()->input_in_progress() &&
1556 edit_bookmarks_enabled_
.GetValue() &&
1557 !IsBookmarkStarHiddenByExtension()) {
1558 gtk_widget_show_all(star_
.get());
1559 int id
= starred_
? IDR_STAR_LIT
: IDR_STAR
;
1560 gtk_image_set_from_pixbuf(GTK_IMAGE(star_image_
),
1561 theme_service_
->GetImageNamed(id
).ToGdkPixbuf());
1562 gtk_widget_set_tooltip_text(star_
.get(), l10n_util::GetStringUTF8(
1563 starred_
? IDS_TOOLTIP_STARRED
: IDS_TOOLTIP_STAR
).c_str());
1565 gtk_widget_hide_all(star_
.get());
1569 bool LocationBarViewGtk::ShouldOnlyShowLocation() {
1570 return !browser_
->is_type_tabbed();
1573 ////////////////////////////////////////////////////////////////////////////////
1574 // LocationBarViewGtk::PageToolViewGtk
1576 LocationBarViewGtk::PageToolViewGtk::PageToolViewGtk()
1577 : alignment_(gtk_alignment_new(0, 0, 1, 1)),
1578 event_box_(gtk_event_box_new()),
1579 hbox_(gtk_hbox_new(FALSE
, kInnerPadding
)),
1580 image_(gtk_image_new()),
1581 label_(gtk_label_new(NULL
)),
1583 weak_factory_(this) {
1584 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_
.get()), 1, 1, 0, 0);
1585 gtk_container_add(GTK_CONTAINER(alignment_
.get()), event_box_
.get());
1587 // Make the event box not visible so it does not paint a background.
1588 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_
.get()), FALSE
);
1589 g_signal_connect(event_box_
.get(), "button-press-event",
1590 G_CALLBACK(&OnButtonPressedThunk
), this);
1591 g_signal_connect(event_box_
.get(), "expose-event",
1592 G_CALLBACK(&OnExposeThunk
), this);
1594 gtk_widget_set_no_show_all(label_
.get(), TRUE
);
1595 gtk_label_set_line_wrap(GTK_LABEL(label_
.get()), FALSE
);
1597 gtk_box_pack_start(GTK_BOX(hbox_
), image_
.get(), FALSE
, FALSE
, 0);
1598 gtk_box_pack_start(GTK_BOX(hbox_
), label_
.get(), FALSE
, FALSE
, 0);
1600 gtk_container_set_border_width(GTK_CONTAINER(hbox_
), kHboxBorder
);
1602 gtk_container_add(GTK_CONTAINER(event_box_
.get()), hbox_
);
1603 gtk_widget_hide(widget());
1605 animation_
.SetSlideDuration(kPageToolAnimationTime
);
1608 LocationBarViewGtk::PageToolViewGtk::~PageToolViewGtk() {
1611 event_box_
.Destroy();
1612 alignment_
.Destroy();
1615 bool LocationBarViewGtk::PageToolViewGtk::IsVisible() {
1616 return gtk_widget_get_visible(widget());
1619 void LocationBarViewGtk::PageToolViewGtk::AnimationProgressed(
1620 const gfx::Animation
* animation
) {
1621 gtk_widget_set_size_request(
1623 animation
->GetCurrentValue() * label_req_
.width
,
1627 void LocationBarViewGtk::PageToolViewGtk::AnimationEnded(
1628 const gfx::Animation
* animation
) {
1631 void LocationBarViewGtk::PageToolViewGtk::AnimationCanceled(
1632 const gfx::Animation
* animation
) {
1635 void LocationBarViewGtk::PageToolViewGtk::StartAnimating() {
1636 if (animation_
.IsShowing() || animation_
.IsClosing())
1639 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_
.get()), TRUE
);
1640 GdkColor border_color
= GetButtonBorderColor();
1641 gtk_util::ActAsRoundedWindow(event_box_
.get(), border_color
,
1643 gtk_util::ROUNDED_ALL
, gtk_util::BORDER_ALL
);
1645 gtk_widget_set_size_request(label_
.get(), -1, -1);
1646 gtk_widget_size_request(label_
.get(), &label_req_
);
1647 gtk_widget_set_size_request(label_
.get(), 0, -1);
1648 gtk_widget_show(label_
.get());
1653 void LocationBarViewGtk::PageToolViewGtk::CloseAnimation() {
1657 gboolean
LocationBarViewGtk::PageToolViewGtk::OnButtonPressed(
1658 GtkWidget
* sender
, GdkEvent
* event
) {
1663 gboolean
LocationBarViewGtk::PageToolViewGtk::OnExpose(
1664 GtkWidget
* sender
, GdkEventExpose
* event
) {
1665 TRACE_EVENT0("ui::gtk", "LocationBarViewGtk::PageToolViewGtk::OnExpose");
1667 if (!(animation_
.IsShowing() || animation_
.IsClosing()))
1670 GtkAllocation allocation
;
1671 gtk_widget_get_allocation(sender
, &allocation
);
1672 const int height
= allocation
.height
;
1674 cairo_t
* cr
= gdk_cairo_create(gtk_widget_get_window(sender
));
1675 gdk_cairo_rectangle(cr
, &event
->area
);
1678 cairo_pattern_t
* pattern
= cairo_pattern_create_linear(0, 0, 0, height
);
1680 const GdkColor top_color
= GetGradientTopColor();
1681 const GdkColor bottom_color
= GetGradientBottomColor();
1682 cairo_pattern_add_color_stop_rgb(
1684 top_color
.red
/255.0,
1685 top_color
.blue
/255.0,
1686 top_color
.green
/255.0);
1687 cairo_pattern_add_color_stop_rgb(
1689 bottom_color
.red
/255.0,
1690 bottom_color
.blue
/255.0,
1691 bottom_color
.green
/255.0);
1693 cairo_set_source(cr
, pattern
);
1695 cairo_pattern_destroy(pattern
);
1701 ////////////////////////////////////////////////////////////////////////////////
1702 // LocationBarViewGtk::PageActionViewGtk
1704 LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
1705 LocationBarViewGtk
* owner
,
1706 ExtensionAction
* page_action
)
1708 page_action_(page_action
),
1709 current_tab_id_(-1),
1712 preview_enabled_(false) {
1713 event_box_
.Own(gtk_event_box_new());
1714 gtk_widget_set_size_request(event_box_
.get(),
1715 extensions::IconsInfo::kPageActionIconMaxSize
,
1716 extensions::IconsInfo::kPageActionIconMaxSize
);
1718 // Make the event box not visible so it does not paint a background.
1719 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_
.get()), FALSE
);
1720 g_signal_connect(event_box_
.get(), "button-press-event",
1721 G_CALLBACK(&OnButtonPressedThunk
), this);
1722 g_signal_connect_after(event_box_
.get(), "expose-event",
1723 G_CALLBACK(OnExposeEventThunk
), this);
1724 g_signal_connect(event_box_
.get(), "realize",
1725 G_CALLBACK(OnRealizeThunk
), this);
1727 image_
.Own(gtk_image_new());
1728 gtk_container_add(GTK_CONTAINER(event_box_
.get()), image_
.get());
1730 const Extension
* extension
=
1731 owner
->profile()->GetExtensionService()->GetExtensionById(
1732 page_action
->extension_id(), false);
1735 icon_factory_
.reset(new ExtensionActionIconFactory(
1736 owner
->profile(), extension
, page_action
, this));
1738 // We set the owner last of all so that we can determine whether we are in
1739 // the process of initializing this class or not.
1743 LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() {
1744 DisconnectPageActionAccelerator();
1747 event_box_
.Destroy();
1750 bool LocationBarViewGtk::PageActionViewGtk::IsVisible() {
1751 return gtk_widget_get_visible(widget());
1754 void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility(
1755 WebContents
* contents
, const GURL
& url
) {
1756 // Save this off so we can pass it back to the extension when the action gets
1757 // executed. See PageActionImageView::OnMousePressed.
1759 contents
? extensions::ExtensionTabUtil::GetTabId(contents
) : -1;
1762 bool visible
= contents
&&
1763 (preview_enabled_
|| page_action_
->GetIsVisible(current_tab_id_
));
1766 gtk_widget_set_tooltip_text(event_box_
.get(),
1767 page_action_
->GetTitle(current_tab_id_
).c_str());
1770 gfx::Image icon
= icon_factory_
->GetIcon(current_tab_id_
);
1771 if (!icon
.IsEmpty()) {
1772 GdkPixbuf
* pixbuf
= icon
.ToGdkPixbuf();
1774 gtk_image_set_from_pixbuf(GTK_IMAGE(image_
.get()), pixbuf
);
1778 bool old_visible
= IsVisible();
1780 gtk_widget_show_all(event_box_
.get());
1782 gtk_widget_hide_all(event_box_
.get());
1784 if (visible
!= old_visible
) {
1785 content::NotificationService::current()->Notify(
1786 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED
,
1787 content::Source
<ExtensionAction
>(page_action_
),
1788 content::Details
<WebContents
>(contents
));
1792 void LocationBarViewGtk::PageActionViewGtk::OnIconUpdated() {
1793 // If we have no owner, that means this class is still being constructed.
1794 WebContents
* web_contents
= owner_
? owner_
->GetWebContents() : NULL
;
1796 UpdateVisibility(web_contents
, current_url_
);
1799 void LocationBarViewGtk::PageActionViewGtk::TestActivatePageAction() {
1800 GdkEventButton event
= {};
1801 event
.type
= GDK_BUTTON_PRESS
;
1803 OnButtonPressed(widget(), &event
);
1806 void LocationBarViewGtk::PageActionViewGtk::Observe(
1808 const content::NotificationSource
& source
,
1809 const content::NotificationDetails
& details
) {
1810 DCHECK_EQ(type
, chrome::NOTIFICATION_WINDOW_CLOSED
);
1811 DisconnectPageActionAccelerator();
1814 void LocationBarViewGtk::PageActionViewGtk::InspectPopup(
1815 ExtensionAction
* action
) {
1816 ExtensionPopupGtk::Show(
1817 action
->GetPopupUrl(current_tab_id_
),
1820 ExtensionPopupGtk::SHOW_AND_INSPECT
);
1823 void LocationBarViewGtk::PageActionViewGtk::ConnectPageActionAccelerator() {
1824 const extensions::ExtensionSet
* extensions
=
1825 owner_
->profile()->GetExtensionService()->extensions();
1826 const Extension
* extension
=
1827 extensions
->GetByID(page_action_
->extension_id());
1828 window_
= owner_
->browser()->window()->GetNativeWindow();
1830 extensions::CommandService
* command_service
=
1831 extensions::CommandService::Get(owner_
->profile());
1833 extensions::Command command_page_action
;
1834 if (command_service
->GetPageActionCommand(
1836 extensions::CommandService::ACTIVE_ONLY
,
1837 &command_page_action
,
1839 // Found the page action shortcut command, register it.
1840 page_action_keybinding_
.reset(
1841 new ui::Accelerator(command_page_action
.accelerator()));
1844 if (page_action_keybinding_
.get()) {
1845 accel_group_
= gtk_accel_group_new();
1846 gtk_window_add_accel_group(window_
, accel_group_
);
1848 gtk_accel_group_connect(
1850 ui::GetGdkKeyCodeForAccelerator(*page_action_keybinding_
),
1851 ui::GetGdkModifierForAccelerator(*page_action_keybinding_
),
1853 g_cclosure_new(G_CALLBACK(OnGtkAccelerator
), this, NULL
));
1855 // Since we've added an accelerator, we'll need to unregister it before
1856 // the window is closed, so we listen for the window being closed.
1857 registrar_
.Add(this,
1858 chrome::NOTIFICATION_WINDOW_CLOSED
,
1859 content::Source
<GtkWindow
>(window_
));
1863 void LocationBarViewGtk::PageActionViewGtk::DisconnectPageActionAccelerator() {
1865 if (page_action_keybinding_
.get()) {
1866 gtk_accel_group_disconnect_key(
1868 ui::GetGdkKeyCodeForAccelerator(*page_action_keybinding_
),
1869 ui::GetGdkModifierForAccelerator(*page_action_keybinding_
));
1871 gtk_window_remove_accel_group(window_
, accel_group_
);
1872 g_object_unref(accel_group_
);
1873 accel_group_
= NULL
;
1874 page_action_keybinding_
.reset(NULL
);
1878 gboolean
LocationBarViewGtk::PageActionViewGtk::OnButtonPressed(
1880 GdkEventButton
* event
) {
1881 // Double and triple-clicks generate both a GDK_BUTTON_PRESS and a
1882 // GDK_[23]BUTTON_PRESS event. We don't want to double-trigger by acting on
1884 if (event
->type
!= GDK_BUTTON_PRESS
)
1887 WebContents
* web_contents
= owner_
->GetWebContents();
1891 ExtensionService
* extension_service
=
1892 owner_
->profile()->GetExtensionService();
1893 if (!extension_service
)
1896 const Extension
* extension
=
1897 extension_service
->extensions()->GetByID(page_action()->extension_id());
1901 LocationBarController
* controller
=
1902 extensions::TabHelper::FromWebContents(web_contents
)->
1903 location_bar_controller();
1905 switch (controller
->OnClicked(extension
->id(), event
->button
)) {
1906 case LocationBarController::ACTION_NONE
:
1909 case LocationBarController::ACTION_SHOW_POPUP
:
1910 ExtensionPopupGtk::Show(
1911 page_action_
->GetPopupUrl(current_tab_id_
),
1914 ExtensionPopupGtk::SHOW
);
1917 case LocationBarController::ACTION_SHOW_CONTEXT_MENU
:
1918 context_menu_model_
=
1919 new ExtensionContextMenuModel(extension
, owner_
->browser_
, this);
1920 context_menu_
.reset(
1921 new MenuGtk(NULL
, context_menu_model_
.get()));
1922 context_menu_
->PopupForWidget(sender
, event
->button
, event
->time
);
1929 gboolean
LocationBarViewGtk::PageActionViewGtk::OnExposeEvent(
1931 GdkEventExpose
* event
) {
1932 TRACE_EVENT0("ui::gtk", "LocationBarViewGtk::PageActionViewGtk::OnExpose");
1933 WebContents
* contents
= owner_
->GetWebContents();
1937 int tab_id
= extensions::ExtensionTabUtil::GetTabId(contents
);
1941 std::string badge_text
= page_action_
->GetBadgeText(tab_id
);
1942 if (badge_text
.empty())
1945 gfx::CanvasSkiaPaint
canvas(event
, false);
1946 GtkAllocation allocation
;
1947 gtk_widget_get_allocation(widget
, &allocation
);
1948 page_action_
->PaintBadge(&canvas
, gfx::Rect(allocation
), tab_id
);
1952 void LocationBarViewGtk::PageActionViewGtk::OnRealize(GtkWidget
* widget
) {
1953 ConnectPageActionAccelerator();
1957 gboolean
LocationBarViewGtk::PageActionViewGtk::OnGtkAccelerator(
1958 GtkAccelGroup
* accel_group
,
1959 GObject
* acceleratable
,
1961 GdkModifierType modifier
,
1963 PageActionViewGtk
* view
= static_cast<PageActionViewGtk
*>(user_data
);
1964 if (!gtk_widget_get_visible(view
->widget()))
1967 GdkEventButton event
= {};
1968 event
.type
= GDK_BUTTON_PRESS
;
1970 return view
->OnButtonPressed(view
->widget(), &event
);