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