Home | History | Annotate | Download | only in gtk
      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