1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_ 6 #define CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_ 7 8 #include <gtk/gtk.h> 9 10 #include <map> 11 #include <string> 12 13 #include "base/basictypes.h" 14 #include "base/callback.h" 15 #include "base/compiler_specific.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_vector.h" 18 #include "base/memory/weak_ptr.h" 19 #include "base/prefs/pref_member.h" 20 #include "chrome/browser/extensions/extension_action.h" 21 #include "chrome/browser/extensions/extension_action_icon_factory.h" 22 #include "chrome/browser/extensions/extension_context_menu_model.h" 23 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h" 24 #include "chrome/browser/ui/gtk/menu_gtk.h" 25 #include "chrome/browser/ui/omnibox/location_bar.h" 26 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h" 27 #include "chrome/browser/ui/view_ids.h" 28 #include "chrome/common/content_settings_types.h" 29 #include "content/public/browser/notification_observer.h" 30 #include "content/public/browser/notification_registrar.h" 31 #include "content/public/common/page_transition_types.h" 32 #include "ui/base/gtk/gtk_signal.h" 33 #include "ui/base/gtk/owned_widget_gtk.h" 34 #include "ui/base/window_open_disposition.h" 35 #include "ui/gfx/animation/animation_delegate.h" 36 #include "ui/gfx/animation/slide_animation.h" 37 #include "url/gurl.h" 38 39 class Browser; 40 class CommandUpdater; 41 class ContentSettingImageModel; 42 class ContentSettingBubbleGtk; 43 class ExtensionAction; 44 class GtkThemeService; 45 class OmniboxViewGtk; 46 47 namespace content { 48 class WebContents; 49 } 50 51 namespace gfx { 52 class Image; 53 } 54 55 namespace ui { 56 class Accelerator; 57 } 58 59 class LocationBarViewGtk : public OmniboxEditController, 60 public LocationBar, 61 public LocationBarTesting, 62 public content::NotificationObserver { 63 public: 64 explicit LocationBarViewGtk(Browser* browser); 65 virtual ~LocationBarViewGtk(); 66 67 void Init(bool popup_window_mode); 68 69 // Returns the widget the caller should host. You must call Init() first. 70 GtkWidget* widget() { return hbox_.get(); } 71 72 // Returns the widget the page info bubble should point to. 73 GtkWidget* location_icon_widget() const { return location_icon_image_; } 74 75 // Returns the widget the extension installed bubble should point to. 76 GtkWidget* location_entry_widget() const { return entry_box_; } 77 78 Browser* browser() const { return browser_; } 79 80 // Sets |preview_enabled| for the PageActionViewGtk associated with this 81 // |page_action|. If |preview_enabled| is true, the view will display the 82 // page action's icon even though it has not been activated by the extension. 83 // This is used by the ExtensionInstalledBubbleGtk to preview what the icon 84 // will look like for the user upon installation of the extension. 85 void SetPreviewEnabledPageAction(ExtensionAction *page_action, 86 bool preview_enabled); 87 88 // Retrieves the GtkWidget which is associated with PageActionView 89 // corresponding to |page_action|. 90 GtkWidget* GetPageActionWidget(ExtensionAction* page_action); 91 92 // Show the bookmark bubble. 93 void ShowStarBubble(const GURL& url, bool newly_boomkarked); 94 95 // Happens when the zoom changes for the active tab. |can_show_bubble| will be 96 // true if it was a user action and a bubble could be shown. 97 void ZoomChangedForActiveTab(bool can_show_bubble); 98 99 // Returns the zoom widget. Used by the zoom bubble for an anchor. 100 GtkWidget* zoom_widget() { return zoom_.get(); } 101 102 // Returns the manage passwords widget. Used by the manage passwords bubble 103 // for an anchor. 104 GtkWidget* manage_passwords_icon_widget() { 105 return manage_passwords_icon_.get(); 106 } 107 108 // Set the starred state of the bookmark star. 109 void SetStarred(bool starred); 110 111 // OmniboxEditController: 112 virtual void Update(const content::WebContents* contents) OVERRIDE; 113 virtual void OnChanged() OVERRIDE; 114 virtual void OnSetFocus() OVERRIDE; 115 virtual InstantController* GetInstant() OVERRIDE; 116 virtual content::WebContents* GetWebContents() OVERRIDE; 117 virtual ToolbarModel* GetToolbarModel() OVERRIDE; 118 virtual const ToolbarModel* GetToolbarModel() const OVERRIDE; 119 120 // LocationBar: 121 virtual void ShowFirstRunBubble() OVERRIDE; 122 virtual GURL GetDestinationURL() const OVERRIDE; 123 virtual WindowOpenDisposition GetWindowOpenDisposition() const OVERRIDE; 124 virtual content::PageTransition GetPageTransition() const OVERRIDE; 125 virtual void AcceptInput() OVERRIDE; 126 virtual void FocusLocation(bool select_all) OVERRIDE; 127 virtual void FocusSearch() OVERRIDE; 128 virtual void UpdateContentSettingsIcons() OVERRIDE; 129 virtual void UpdateManagePasswordsIconAndBubble() OVERRIDE; 130 virtual void UpdatePageActions() OVERRIDE; 131 virtual void InvalidatePageActions() OVERRIDE; 132 virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE; 133 virtual void UpdateGeneratedCreditCardView() OVERRIDE; 134 virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE; 135 virtual void Revert() OVERRIDE; 136 virtual const OmniboxView* GetOmniboxView() const OVERRIDE; 137 virtual OmniboxView* GetOmniboxView() OVERRIDE; 138 virtual LocationBarTesting* GetLocationBarForTesting() OVERRIDE; 139 140 // LocationBarTesting: 141 virtual int PageActionCount() OVERRIDE; 142 virtual int PageActionVisibleCount() OVERRIDE; 143 virtual ExtensionAction* GetPageAction(size_t index) OVERRIDE; 144 virtual ExtensionAction* GetVisiblePageAction(size_t index) OVERRIDE; 145 virtual void TestPageActionPressed(size_t index) OVERRIDE; 146 virtual bool GetBookmarkStarVisibility() OVERRIDE; 147 148 // content::NotificationObserver: 149 virtual void Observe(int type, 150 const content::NotificationSource& source, 151 const content::NotificationDetails& details) OVERRIDE; 152 153 // Edit background color. 154 static const GdkColor kBackgroundColor; 155 156 // Superclass for content settings icons shown at the left side of the 157 // location bar. 158 class PageToolViewGtk : public gfx::AnimationDelegate { 159 public: 160 PageToolViewGtk(); 161 virtual ~PageToolViewGtk(); 162 163 GtkWidget* widget() { return alignment_.get(); } 164 165 bool IsVisible(); 166 167 virtual void Update(content::WebContents* web_contents) = 0; 168 169 // Overridden from gfx::AnimationDelegate: 170 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 171 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 172 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; 173 174 protected: 175 // Theme constants for solid background elements. 176 virtual GdkColor GetButtonBorderColor() const = 0; 177 virtual GdkColor GetGradientTopColor() const = 0; 178 virtual GdkColor GetGradientBottomColor() const = 0; 179 180 // Delegate for ButtonPressed message. 181 virtual void OnClick(GtkWidget* sender) = 0; 182 183 // Start the process of showing the label. 184 void StartAnimating(); 185 186 // Slide the label shut. 187 void CloseAnimation(); 188 189 CHROMEGTK_CALLBACK_1(PageToolViewGtk, gboolean, OnButtonPressed, GdkEvent*); 190 CHROMEGTK_CALLBACK_1(PageToolViewGtk, gboolean, OnExpose, GdkEventExpose*); 191 192 // The widgets for this view. 193 ui::OwnedWidgetGtk alignment_; 194 ui::OwnedWidgetGtk event_box_; 195 GtkWidget* hbox_; 196 ui::OwnedWidgetGtk image_; 197 198 // Explanatory text (e.g. "popup blocked"). 199 ui::OwnedWidgetGtk label_; 200 201 // When we show explanatory text, we slide it in/out. 202 gfx::SlideAnimation animation_; 203 204 // The label's default requisition (cached so we can animate accordingly). 205 GtkRequisition label_req_; 206 207 base::WeakPtrFactory<PageToolViewGtk> weak_factory_; 208 209 private: 210 DISALLOW_COPY_AND_ASSIGN(PageToolViewGtk); 211 }; 212 213 private: 214 class PageActionViewGtk : 215 public ExtensionActionIconFactory::Observer, 216 public content::NotificationObserver, 217 public ExtensionContextMenuModel::PopupDelegate, 218 public ExtensionAction::IconAnimation::Observer { 219 public: 220 PageActionViewGtk(LocationBarViewGtk* owner, ExtensionAction* page_action); 221 virtual ~PageActionViewGtk(); 222 223 GtkWidget* widget() { return event_box_.get(); } 224 225 ExtensionAction* page_action() { return page_action_; } 226 227 void set_preview_enabled(bool preview_enabled) { 228 preview_enabled_ = preview_enabled; 229 } 230 231 bool IsVisible(); 232 233 // Called to notify the PageAction that it should determine whether to be 234 // visible or hidden. |contents| is the WebContents that is active, |url| 235 // is the current page URL. 236 void UpdateVisibility(content::WebContents* contents, const GURL& url); 237 238 // Overriden from ExtensionActionIconFactory::Observer. 239 virtual void OnIconUpdated() OVERRIDE; 240 241 // Simulate left mouse click on the page action button. 242 void TestActivatePageAction(); 243 244 // Implement the content::NotificationObserver interface. 245 virtual void Observe(int type, 246 const content::NotificationSource& source, 247 const content::NotificationDetails& details) OVERRIDE; 248 249 // Overridden from ExtensionContextMenuModel::PopupDelegate: 250 virtual void InspectPopup(ExtensionAction* action) OVERRIDE; 251 252 private: 253 // Connect the accelerator for the page action popup. 254 void ConnectPageActionAccelerator(); 255 256 // Disconnect the accelerator for the page action popup. 257 void DisconnectPageActionAccelerator(); 258 259 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed, 260 GdkEventButton*); 261 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent, 262 GdkEventExpose*); 263 CHROMEGTK_CALLBACK_0(PageActionViewGtk, void, OnRealize); 264 265 // The accelerator handler for when the shortcuts to open the popup is 266 // struck. 267 static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group, 268 GObject* acceleratable, 269 guint keyval, 270 GdkModifierType modifier, 271 void* user_data); 272 273 // ExtensionAction::IconAnimationDelegate implementation. 274 virtual void OnIconChanged() OVERRIDE; 275 276 // The location bar view that owns us. 277 LocationBarViewGtk* owner_; 278 279 // The PageAction that this view represents. The PageAction is not owned by 280 // us, it resides in the extension of this particular profile. 281 ExtensionAction* page_action_; 282 283 // The object that will be used to get the extension action icon for us. 284 // It may load the icon asynchronously (in which case the initial icon 285 // returned by the factory will be transparent), so we have to observe it 286 // for updates to the icon. 287 scoped_ptr<ExtensionActionIconFactory> icon_factory_; 288 289 // The widgets for this page action. 290 ui::OwnedWidgetGtk event_box_; 291 ui::OwnedWidgetGtk image_; 292 293 // The tab id we are currently showing the icon for. 294 int current_tab_id_; 295 296 // The URL we are currently showing the icon for. 297 GURL current_url_; 298 299 // The native browser window of the location bar that owns us. 300 gfx::NativeWindow window_; 301 302 // The Notification registrar. 303 content::NotificationRegistrar registrar_; 304 305 // The accelerator group used to handle accelerators, owned by this object. 306 GtkAccelGroup* accel_group_; 307 308 // The keybinding accelerator registered to show the page action popup. 309 scoped_ptr<ui::Accelerator> page_action_keybinding_; 310 // The keybinding accelerator registered to show the script badge popup. 311 scoped_ptr<ui::Accelerator> script_badge_keybinding_; 312 313 // This is used for post-install visual feedback. The page_action icon 314 // is briefly shown even if it hasn't been enabled by its extension. 315 bool preview_enabled_; 316 317 // The context menu view and model for this extension action. 318 scoped_ptr<MenuGtk> context_menu_; 319 scoped_refptr<ExtensionContextMenuModel> context_menu_model_; 320 321 // Fade-in animation for the icon with observer scoped to this. 322 ExtensionAction::IconAnimation::ScopedObserver 323 scoped_icon_animation_observer_; 324 325 DISALLOW_COPY_AND_ASSIGN(PageActionViewGtk); 326 }; 327 friend class PageActionViewGtk; 328 329 // Creates, initializes, and packs the location icon, EV certificate name, 330 // and optional border. 331 void BuildSiteTypeArea(); 332 333 // Enable or disable the location icon/EV certificate as a drag source for 334 // the URL. 335 void SetSiteTypeDragSource(); 336 337 GtkWidget* site_type_area() { return site_type_alignment_; } 338 339 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, HandleExpose, 340 GdkEventExpose*); 341 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnIconReleased, 342 GdkEventButton*); 343 CHROMEGTK_CALLBACK_4(LocationBarViewGtk, void, OnIconDragData, 344 GdkDragContext*, GtkSelectionData*, guint, guint); 345 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragBegin, 346 GdkDragContext*); 347 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragEnd, 348 GdkDragContext*); 349 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnHboxSizeAllocate, 350 GtkAllocation*); 351 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnEntryBoxSizeAllocate, 352 GtkAllocation*); 353 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnZoomButtonPress, 354 GdkEventButton*); 355 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, 356 OnManagePasswordsIconButtonPress, GdkEventButton*); 357 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnScriptBubbleButtonPress, 358 GdkEventButton*); 359 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnStarButtonSizeAllocate, 360 GtkAllocation*); 361 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnStarButtonPress, 362 GdkEventButton*); 363 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, 364 OnScriptBubbleButtonExpose, GdkEventExpose*); 365 366 // Updates the site type area: changes the icon and shows/hides the EV 367 // certificate information. 368 void UpdateSiteTypeArea(); 369 370 // Updates the maximum size of the EV certificate label. 371 void UpdateEVCertificateLabelSize(); 372 373 // Set the keyword text for the Search BLAH: keyword box. 374 void SetKeywordLabel(const base::string16& keyword); 375 376 // Set the keyword text for the "Press tab to search BLAH" hint box. 377 void SetKeywordHintLabel(const base::string16& keyword); 378 379 void ShowFirstRunBubbleInternal(); 380 381 // Shows the zoom bubble. 382 void ShowZoomBubble(); 383 384 // Shows the manage password bubble. 385 void ShowManagePasswordsBubble(); 386 387 // Show or hide |tab_to_search_box_| and |tab_to_search_hint_| according to 388 // the value of |show_selected_keyword_|, |show_keyword_hint_|, and the 389 // available horizontal space in the location bar. 390 void AdjustChildrenVisibility(); 391 392 // Helpers to build create the various buttons that show up in the location 393 // bar. 394 GtkWidget* CreateIconButton( 395 GtkWidget** image, 396 int image_id, 397 ViewID debug_id, 398 int tooltip_id, 399 gboolean (click_callback)(GtkWidget*, GdkEventButton*, gpointer)); 400 void CreateZoomButton(); 401 void CreateManagePasswordsIconButton(); 402 void CreateScriptBubbleButton(); 403 void CreateStarButton(); 404 405 // Helpers to update state of the various buttons that show up in the 406 // location bar. 407 void UpdateZoomIcon(); 408 void UpdateManagePasswordsIcon(); 409 void UpdateScriptBubbleIcon(); 410 void UpdateStarIcon(); 411 412 // Shows the managepassword bubble in case there is a password to be saved. 413 void ShowManagePasswordsBubbleIfNeeded(); 414 415 // Returns true if we should only show the URL and none of the extras like 416 // the star button or page actions. 417 bool ShouldOnlyShowLocation(); 418 419 // The outermost widget we want to be hosted. 420 ui::OwnedWidgetGtk hbox_; 421 422 // Zoom button. 423 ui::OwnedWidgetGtk zoom_; 424 GtkWidget* zoom_image_; 425 426 // Manage passwords button. 427 ui::OwnedWidgetGtk manage_passwords_icon_; 428 GtkWidget* manage_passwords_icon_image_; 429 430 ui::OwnedWidgetGtk script_bubble_button_; 431 GtkWidget* script_bubble_button_image_; 432 size_t num_running_scripts_; 433 434 // Star button. 435 ui::OwnedWidgetGtk star_; 436 GtkWidget* star_image_; 437 bool starred_; 438 bool star_sized_; // True after a size-allocate signal to the star widget. 439 440 // Action to execute after the star icon has been sized, can refer to a NULL 441 // function to indicate no such action should be taken. 442 base::Closure on_star_sized_; 443 444 // An icon to the left of the address bar. 445 GtkWidget* site_type_alignment_; 446 GtkWidget* site_type_event_box_; 447 GtkWidget* location_icon_image_; 448 GtkWidget* drag_icon_; 449 bool enable_location_drag_; 450 // TODO(pkasting): Split this label off and move the rest of the items to the 451 // left of the address bar. 452 GtkWidget* security_info_label_; 453 454 // Content setting icons. 455 ui::OwnedWidgetGtk content_setting_hbox_; 456 ScopedVector<PageToolViewGtk> content_setting_views_; 457 458 // Extension page actions. 459 std::vector<ExtensionAction*> page_actions_; 460 461 // Extension page action icons. 462 ui::OwnedWidgetGtk page_action_hbox_; 463 ScopedVector<PageActionViewGtk> page_action_views_; 464 465 // The widget that contains our tab hints and the location bar. 466 GtkWidget* entry_box_; 467 468 // Area on the left shown when in tab to search mode. 469 GtkWidget* tab_to_search_alignment_; 470 GtkWidget* tab_to_search_box_; 471 GtkWidget* tab_to_search_magnifier_; 472 GtkWidget* tab_to_search_full_label_; 473 GtkWidget* tab_to_search_partial_label_; 474 475 // Hint to user that they can tab-to-search by hitting tab. 476 GtkWidget* tab_to_search_hint_; 477 GtkWidget* tab_to_search_hint_leading_label_; 478 GtkWidget* tab_to_search_hint_icon_; 479 GtkWidget* tab_to_search_hint_trailing_label_; 480 481 scoped_ptr<OmniboxViewGtk> omnibox_view_; 482 483 // Alignment used to wrap |omnibox_view_|. 484 GtkWidget* omnibox_view_alignment_; 485 486 Browser* browser_; 487 488 // When true, the location bar view is read only and also is has a slightly 489 // different presentation (font size / color). This is used for popups. 490 bool popup_window_mode_; 491 492 // Provides colors and rendering mode. 493 GtkThemeService* theme_service_; 494 495 content::NotificationRegistrar registrar_; 496 497 // Width of the main |hbox_|. Used to properly elide the EV certificate. 498 int hbox_width_; 499 500 // Width of the hbox that holds |tab_to_search_box_|, |omnibox_view_| and 501 // |tab_to_search_hint_|. 502 int entry_box_width_; 503 504 // Indicate if |tab_to_search_box_| should be shown. 505 bool show_selected_keyword_; 506 507 // Indicate if |tab_to_search_hint_| should be shown. 508 bool show_keyword_hint_; 509 510 // The last search keyword that was shown via the |tab_to_search_box_|. 511 base::string16 last_keyword_; 512 513 // Used to change the visibility of the star decoration. 514 BooleanPrefMember edit_bookmarks_enabled_; 515 516 // Used to remember the URL and title text when drag&drop has begun. 517 GURL drag_url_; 518 base::string16 drag_title_; 519 520 // Used to schedule a task for the first run bubble. 521 base::WeakPtrFactory<LocationBarViewGtk> weak_ptr_factory_; 522 523 DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk); 524 }; 525 526 #endif // CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_ 527