1 // Copyright (c) 2011 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 #pragma once 8 9 #include <gtk/gtk.h> 10 11 #include <map> 12 #include <string> 13 14 #include "base/basictypes.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_vector.h" 17 #include "chrome/browser/autocomplete/autocomplete_edit.h" 18 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" 19 #include "chrome/browser/extensions/extension_context_menu_model.h" 20 #include "chrome/browser/extensions/image_loading_tracker.h" 21 #include "chrome/browser/first_run/first_run.h" 22 #include "chrome/browser/prefs/pref_member.h" 23 #include "chrome/browser/ui/gtk/info_bubble_gtk.h" 24 #include "chrome/browser/ui/gtk/menu_gtk.h" 25 #include "chrome/browser/ui/gtk/owned_widget_gtk.h" 26 #include "chrome/browser/ui/omnibox/location_bar.h" 27 #include "chrome/common/content_settings_types.h" 28 #include "content/common/notification_observer.h" 29 #include "content/common/notification_registrar.h" 30 #include "content/common/page_transition_types.h" 31 #include "third_party/skia/include/core/SkBitmap.h" 32 #include "ui/base/animation/slide_animation.h" 33 #include "ui/base/gtk/gtk_signal.h" 34 #include "webkit/glue/window_open_disposition.h" 35 36 class AutocompleteEditViewGtk; 37 class Browser; 38 class CommandUpdater; 39 class ContentSettingImageModel; 40 class ContentSettingBubbleGtk; 41 class ExtensionAction; 42 class GtkThemeService; 43 class Profile; 44 class SkBitmap; 45 class TabContents; 46 class ToolbarModel; 47 48 class LocationBarViewGtk : public AutocompleteEditController, 49 public LocationBar, 50 public LocationBarTesting, 51 public NotificationObserver { 52 public: 53 explicit LocationBarViewGtk(Browser* browser); 54 virtual ~LocationBarViewGtk(); 55 56 void Init(bool popup_window_mode); 57 58 void SetProfile(Profile* profile); 59 60 // Returns the widget the caller should host. You must call Init() first. 61 GtkWidget* widget() { return hbox_.get(); } 62 63 // Returns the widget the page info bubble should point to. 64 GtkWidget* location_icon_widget() const { return location_icon_image_; } 65 66 // Returns the widget the extension installed bubble should point to. 67 GtkWidget* location_entry_widget() const { return entry_box_; } 68 69 // Returns the current TabContents. 70 TabContents* GetTabContents() const; 71 72 // Sets |preview_enabled| for the PageActionViewGtk associated with this 73 // |page_action|. If |preview_enabled| is true, the view will display the 74 // page action's icon even though it has not been activated by the extension. 75 // This is used by the ExtensionInstalledBubbleGtk to preview what the icon 76 // will look like for the user upon installation of the extension. 77 void SetPreviewEnabledPageAction(ExtensionAction *page_action, 78 bool preview_enabled); 79 80 // Retrieves the GtkWidget which is associated with PageActionView 81 // corresponding to |page_action|. 82 GtkWidget* GetPageActionWidget(ExtensionAction* page_action); 83 84 // Updates the location bar. We also reset the bar's permanent text and 85 // security style, and, if |tab_for_state_restoring| is non-NULL, also 86 // restore saved state that the tab holds. 87 void Update(const TabContents* tab_for_state_restoring); 88 89 // Show the bookmark bubble. 90 void ShowStarBubble(const GURL& url, bool newly_boomkarked); 91 92 // Set the starred state of the bookmark star. 93 void SetStarred(bool starred); 94 95 // Implement the AutocompleteEditController interface. 96 virtual void OnAutocompleteAccept(const GURL& url, 97 WindowOpenDisposition disposition, 98 PageTransition::Type transition, 99 const GURL& alternate_nav_url) OVERRIDE; 100 virtual void OnChanged() OVERRIDE; 101 virtual void OnSelectionBoundsChanged() OVERRIDE; 102 virtual void OnKillFocus() OVERRIDE; 103 virtual void OnSetFocus() OVERRIDE; 104 virtual void OnInputInProgress(bool in_progress) OVERRIDE; 105 virtual SkBitmap GetFavicon() const OVERRIDE; 106 virtual string16 GetTitle() const OVERRIDE; 107 virtual InstantController* GetInstant() OVERRIDE; 108 virtual TabContentsWrapper* GetTabContentsWrapper() const OVERRIDE; 109 110 // Implement the LocationBar interface. 111 virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type); 112 virtual void SetSuggestedText(const string16& text, 113 InstantCompleteBehavior behavior); 114 virtual std::wstring GetInputString() const; 115 virtual WindowOpenDisposition GetWindowOpenDisposition() const; 116 virtual PageTransition::Type GetPageTransition() const; 117 virtual void AcceptInput(); 118 virtual void FocusLocation(bool select_all); 119 virtual void FocusSearch(); 120 virtual void UpdateContentSettingsIcons(); 121 virtual void UpdatePageActions(); 122 virtual void InvalidatePageActions(); 123 virtual void SaveStateToContents(TabContents* contents); 124 virtual void Revert(); 125 virtual const AutocompleteEditView* location_entry() const; 126 virtual AutocompleteEditView* location_entry(); 127 virtual LocationBarTesting* GetLocationBarForTesting(); 128 129 // Implement the LocationBarTesting interface. 130 virtual int PageActionCount(); 131 virtual int PageActionVisibleCount(); 132 virtual ExtensionAction* GetPageAction(size_t index); 133 virtual ExtensionAction* GetVisiblePageAction(size_t index); 134 virtual void TestPageActionPressed(size_t index); 135 136 // Implement the NotificationObserver interface. 137 virtual void Observe(NotificationType type, 138 const NotificationSource& source, 139 const NotificationDetails& details); 140 141 // Edit background color. 142 static const GdkColor kBackgroundColor; 143 144 private: 145 class ContentSettingImageViewGtk : public InfoBubbleGtkDelegate, 146 public ui::AnimationDelegate { 147 public: 148 ContentSettingImageViewGtk(ContentSettingsType content_type, 149 const LocationBarViewGtk* parent, 150 Profile* profile); 151 virtual ~ContentSettingImageViewGtk(); 152 153 GtkWidget* widget() { return alignment_.get(); } 154 155 void set_profile(Profile* profile) { profile_ = profile; } 156 157 bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); } 158 void UpdateFromTabContents(TabContents* tab_contents); 159 160 // Overridden from ui::AnimationDelegate: 161 virtual void AnimationProgressed(const ui::Animation* animation); 162 virtual void AnimationEnded(const ui::Animation* animation); 163 virtual void AnimationCanceled(const ui::Animation* animation); 164 165 private: 166 // Start the process of showing the label. 167 void StartAnimating(); 168 169 // Slide the label shut. 170 void CloseAnimation(); 171 172 CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnButtonPressed, 173 GdkEvent*); 174 CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnExpose, 175 GdkEventExpose*); 176 177 // InfoBubbleDelegate overrides: 178 virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, 179 bool closed_by_escape); 180 181 scoped_ptr<ContentSettingImageModel> content_setting_image_model_; 182 183 // The widgets for this content settings view. 184 OwnedWidgetGtk alignment_; 185 OwnedWidgetGtk event_box_; 186 GtkWidget* hbox_; 187 OwnedWidgetGtk image_; 188 189 // Explanatory text ("popup blocked"). 190 OwnedWidgetGtk label_; 191 192 // The owning LocationBarViewGtk. 193 const LocationBarViewGtk* parent_; 194 195 // The currently active profile. 196 Profile* profile_; 197 198 // The currently shown info bubble if any. 199 ContentSettingBubbleGtk* info_bubble_; 200 201 // When we show explanatory text, we slide it in/out. 202 ui::SlideAnimation animation_; 203 204 // The label's default requisition (cached so we can animate accordingly). 205 GtkRequisition label_req_; 206 207 ScopedRunnableMethodFactory<ContentSettingImageViewGtk> method_factory_; 208 209 DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk); 210 }; 211 212 class PageActionViewGtk : public ImageLoadingTracker::Observer, 213 public ExtensionContextMenuModel::PopupDelegate { 214 public: 215 PageActionViewGtk( 216 LocationBarViewGtk* owner, Profile* profile, 217 ExtensionAction* page_action); 218 virtual ~PageActionViewGtk(); 219 220 GtkWidget* widget() { return event_box_.get(); } 221 222 ExtensionAction* page_action() { return page_action_; } 223 224 void set_preview_enabled(bool preview_enabled) { 225 preview_enabled_ = preview_enabled; 226 } 227 228 bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); } 229 230 // Called to notify the PageAction that it should determine whether to be 231 // visible or hidden. |contents| is the TabContents that is active, |url| 232 // is the current page URL. 233 void UpdateVisibility(TabContents* contents, const GURL& url); 234 235 // A callback from ImageLoadingTracker for when the image has loaded. 236 virtual void OnImageLoaded( 237 SkBitmap* image, const ExtensionResource& resource, int index); 238 239 // Simulate left mouse click on the page action button. 240 void TestActivatePageAction(); 241 242 // Overridden from ExtensionContextMenuModel::PopupDelegate: 243 virtual void InspectPopup(ExtensionAction* action); 244 245 private: 246 // Show the popup for this page action. If |devtools| is true, show it 247 // with a debugger window attached. Returns true if a popup was shown. 248 bool ShowPopup(bool devtools); 249 250 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed, 251 GdkEventButton*); 252 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent, 253 GdkEventExpose*); 254 255 // The location bar view that owns us. 256 LocationBarViewGtk* owner_; 257 258 // The current profile (not owned by us). 259 Profile* profile_; 260 261 // The PageAction that this view represents. The PageAction is not owned by 262 // us, it resides in the extension of this particular profile. 263 ExtensionAction* page_action_; 264 265 // A cache of all the different icon paths associated with this page action. 266 typedef std::map<std::string, GdkPixbuf*> PixbufMap; 267 PixbufMap pixbufs_; 268 269 // A cache of the last dynamically generated bitmap and the pixbuf that 270 // corresponds to it. We keep track of both so we can free old pixbufs as 271 // their icons are replaced. 272 SkBitmap last_icon_skbitmap_; 273 GdkPixbuf* last_icon_pixbuf_; 274 275 // The object that is waiting for the image loading to complete 276 // asynchronously. 277 ImageLoadingTracker tracker_; 278 279 // The widgets for this page action. 280 OwnedWidgetGtk event_box_; 281 OwnedWidgetGtk image_; 282 283 // The tab id we are currently showing the icon for. 284 int current_tab_id_; 285 286 // The URL we are currently showing the icon for. 287 GURL current_url_; 288 289 // This is used for post-install visual feedback. The page_action icon 290 // is briefly shown even if it hasn't been enabled by its extension. 291 bool preview_enabled_; 292 293 // The context menu view and model for this extension action. 294 scoped_ptr<MenuGtk> context_menu_; 295 scoped_refptr<ExtensionContextMenuModel> context_menu_model_; 296 297 DISALLOW_COPY_AND_ASSIGN(PageActionViewGtk); 298 }; 299 friend class PageActionViewGtk; 300 301 // Creates, initializes, and packs the location icon, EV certificate name, 302 // and optional border. 303 void BuildSiteTypeArea(); 304 305 // Enable or disable the location icon/EV certificate as a drag source for 306 // the URL. 307 void SetSiteTypeDragSource(); 308 309 GtkWidget* site_type_area() { return site_type_alignment_; } 310 311 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, HandleExpose, 312 GdkEventExpose*); 313 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnIconReleased, 314 GdkEventButton*); 315 CHROMEGTK_CALLBACK_4(LocationBarViewGtk, void, OnIconDragData, 316 GdkDragContext*, GtkSelectionData*, guint, guint); 317 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragBegin, 318 GdkDragContext*); 319 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnIconDragEnd, 320 GdkDragContext*); 321 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnHboxSizeAllocate, 322 GtkAllocation*); 323 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnEntryBoxSizeAllocate, 324 GtkAllocation*); 325 CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnStarButtonPress, 326 GdkEventButton*); 327 328 // Updates the site type area: changes the icon and shows/hides the EV 329 // certificate information. 330 void UpdateSiteTypeArea(); 331 332 // Updates the maximum size of the EV certificate label. 333 void UpdateEVCertificateLabelSize(); 334 335 // Sets the text that should be displayed in the info label and its associated 336 // tooltip text. Call with an empty string if the info label should be 337 // hidden. 338 void SetInfoText(); 339 340 // Set the keyword text for the Search BLAH: keyword box. 341 void SetKeywordLabel(const string16& keyword); 342 343 // Set the keyword text for the "Press tab to search BLAH" hint box. 344 void SetKeywordHintLabel(const string16& keyword); 345 346 void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type); 347 348 // Show or hide |tab_to_search_box_| and |tab_to_search_hint_| according to 349 // the value of |show_selected_keyword_|, |show_keyword_hint_|, and the 350 // available horizontal space in the location bar. 351 void AdjustChildrenVisibility(); 352 353 // Build the star icon. 354 void CreateStarButton(); 355 356 // Update the star icon after it is toggled or the theme changes. 357 void UpdateStarIcon(); 358 359 // Returns true if we should only show the URL and none of the extras like 360 // the star button or page actions. 361 bool ShouldOnlyShowLocation(); 362 363 // The outermost widget we want to be hosted. 364 OwnedWidgetGtk hbox_; 365 366 // Star button. 367 OwnedWidgetGtk star_; 368 GtkWidget* star_image_; 369 bool starred_; 370 371 // An icon to the left of the address bar. 372 GtkWidget* site_type_alignment_; 373 GtkWidget* site_type_event_box_; 374 GtkWidget* location_icon_image_; 375 GtkWidget* drag_icon_; 376 bool enable_location_drag_; 377 // TODO(pkasting): Split this label off and move the rest of the items to the 378 // left of the address bar. 379 GtkWidget* security_info_label_; 380 381 // Content setting icons. 382 OwnedWidgetGtk content_setting_hbox_; 383 ScopedVector<ContentSettingImageViewGtk> content_setting_views_; 384 385 // Extension page action icons. 386 OwnedWidgetGtk page_action_hbox_; 387 ScopedVector<PageActionViewGtk> page_action_views_; 388 389 // The widget that contains our tab hints and the location bar. 390 GtkWidget* entry_box_; 391 392 // Area on the left shown when in tab to search mode. 393 GtkWidget* tab_to_search_alignment_; 394 GtkWidget* tab_to_search_box_; 395 GtkWidget* tab_to_search_magnifier_; 396 GtkWidget* tab_to_search_full_label_; 397 GtkWidget* tab_to_search_partial_label_; 398 399 // Hint to user that they can tab-to-search by hitting tab. 400 GtkWidget* tab_to_search_hint_; 401 GtkWidget* tab_to_search_hint_leading_label_; 402 GtkWidget* tab_to_search_hint_icon_; 403 GtkWidget* tab_to_search_hint_trailing_label_; 404 405 scoped_ptr<AutocompleteEditViewGtk> location_entry_; 406 407 // Alignment used to wrap |location_entry_|. 408 GtkWidget* location_entry_alignment_; 409 410 Profile* profile_; 411 CommandUpdater* command_updater_; 412 ToolbarModel* toolbar_model_; 413 Browser* browser_; 414 415 // When we get an OnAutocompleteAccept notification from the autocomplete 416 // edit, we save the input string so we can give it back to the browser on 417 // the LocationBar interface via GetInputString(). 418 std::wstring location_input_; 419 420 // The user's desired disposition for how their input should be opened. 421 WindowOpenDisposition disposition_; 422 423 // The transition type to use for the navigation. 424 PageTransition::Type transition_; 425 426 // Used to schedule a task for the first run info bubble. 427 ScopedRunnableMethodFactory<LocationBarViewGtk> first_run_bubble_; 428 429 // When true, the location bar view is read only and also is has a slightly 430 // different presentation (font size / color). This is used for popups. 431 bool popup_window_mode_; 432 433 // Provides colors and rendering mode. 434 GtkThemeService* theme_service_; 435 436 NotificationRegistrar registrar_; 437 438 // Width of the main |hbox_|. Used to properly elide the EV certificate. 439 int hbox_width_; 440 441 // Width of the hbox that holds |tab_to_search_box_|, |location_entry_| and 442 // |tab_to_search_hint_|. 443 int entry_box_width_; 444 445 // Indicate if |tab_to_search_box_| should be shown. 446 bool show_selected_keyword_; 447 448 // Indicate if |tab_to_search_hint_| should be shown. 449 bool show_keyword_hint_; 450 451 // The last search keyword that was shown via the |tab_to_search_box_|. 452 string16 last_keyword_; 453 454 // Used to change the visibility of the star decoration. 455 BooleanPrefMember edit_bookmarks_enabled_; 456 457 DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk); 458 }; 459 460 #endif // CHROME_BROWSER_UI_GTK_LOCATION_BAR_VIEW_GTK_H_ 461