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
36class AutocompleteEditViewGtk;
37class Browser;
38class CommandUpdater;
39class ContentSettingImageModel;
40class ContentSettingBubbleGtk;
41class ExtensionAction;
42class GtkThemeService;
43class Profile;
44class SkBitmap;
45class TabContents;
46class ToolbarModel;
47
48class 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