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/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