1 // Copyright (c) 2018 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_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_
6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_
7 
8 #include <memory>
9 
10 #include "base/scoped_observer.h"
11 #include "base/time/time.h"
12 #include "base/timer/timer.h"
13 #include "chrome/browser/ui/tabs/tab_utils.h"
14 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
15 
16 namespace gfx {
17 class ImageSkia;
18 }
19 
20 namespace views {
21 class ImageView;
22 class Label;
23 class Widget;
24 }  // namespace views
25 
26 class Tab;
27 
28 // Dialog that displays an informational hover card containing page information.
29 class TabHoverCardBubbleView : public views::BubbleDialogDelegateView {
30  public:
31   explicit TabHoverCardBubbleView(Tab* tab);
32   TabHoverCardBubbleView(const TabHoverCardBubbleView&) = delete;
33   TabHoverCardBubbleView& operator=(const TabHoverCardBubbleView&) = delete;
34   ~TabHoverCardBubbleView() override;
35 
36   // Updates card content and anchoring and shows the tab hover card.
37   void UpdateAndShow(Tab* tab);
38 
39   bool IsVisible();
40 
41   void FadeOutToHide();
42 
43   bool IsFadingOut() const;
44 
45   // Returns the target tab (if any).
46   views::View* GetDesiredAnchorView();
47 
48   // Record a histogram metric of tab hover cards seen prior to a tab being
49   // selected by mouse press.
50   void RecordHoverCardsSeenRatioMetric();
51 
reset_hover_cards_seen_count()52   void reset_hover_cards_seen_count() { hover_cards_seen_count_ = 0; }
53 
54   // BubbleDialogDelegateView:
55   void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
56   ax::mojom::Role GetAccessibleWindowRole() override;
57   void Layout() override;
58 
set_last_mouse_exit_timestamp(base::TimeTicks last_mouse_exit_timestamp)59   void set_last_mouse_exit_timestamp(
60       base::TimeTicks last_mouse_exit_timestamp) {
61     last_mouse_exit_timestamp_ = last_mouse_exit_timestamp;
62   }
63 
64  private:
65   friend class TabHoverCardBubbleViewBrowserTest;
66   friend class TabHoverCardBubbleViewInteractiveUiTest;
67   class WidgetFadeAnimationDelegate;
68   class WidgetSlideAnimationDelegate;
69   class FadeLabel;
70   class ThumbnailObserver;
71 
72   // Get delay in milliseconds based on tab width.
73   base::TimeDelta GetDelay(int tab_width) const;
74 
75   void FadeInToShow();
76 
77   // Updates and formats title, alert state, domain, and preview image.
78   void UpdateCardContent(const Tab* tab);
79 
80   // Update the text fade to the given percent, which should be between 0 and 1.
81   void UpdateTextFade(double percent);
82 
83   void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image);
84   void ClearPreviewImage();
85 
86   // Called when a hover card lands on the tab it's supposed to be a preview
87   // for; happens immediately if there is no slide animation, otherwise when the
88   // animation completes.
89   void OnHoverCardLanded();
90 
91   // views::BubbleDialogDelegateView:
92   gfx::Size CalculatePreferredSize() const override;
93   void OnThemeChanged() override;
94 
95   void RecordTimeSinceLastSeenMetric(base::TimeDelta elapsed_time);
96 
97   // Fade animations interfere with browser tests so we disable them in tests.
98   static bool disable_animations_for_testing_;
99   std::unique_ptr<WidgetFadeAnimationDelegate> fade_animation_delegate_;
100   // Used to animate the tab hover card's movement between tabs.
101   std::unique_ptr<WidgetSlideAnimationDelegate> slide_animation_delegate_;
102   std::unique_ptr<ThumbnailObserver> thumbnail_observer_;
103 
104   // Timestamp of the last time a hover card was visible, recorded before it is
105   // hidden. This is used for metrics.
106   base::TimeTicks last_visible_timestamp_;
107 
108   // Timestamp of the last time the hover card is hidden by the mouse leaving
109   // the tab strip. This is used for reshowing the hover card without delay if
110   // the mouse reenters within a given amount of time.
111   base::TimeTicks last_mouse_exit_timestamp_;
112 
113   views::Label* title_label_ = nullptr;
114   FadeLabel* title_fade_label_ = nullptr;
115   base::Optional<TabAlertState> alert_state_;
116   views::Label* domain_label_ = nullptr;
117   FadeLabel* domain_fade_label_ = nullptr;
118   views::ImageView* preview_image_ = nullptr;
119 
120   // Counter used to keep track of the number of tab hover cards seen before a
121   // tab is selected by mouse press.
122   size_t hover_cards_seen_count_ = 0;
123   bool waiting_for_decompress_ = false;
124 
125   const bool using_rounded_corners_;
126 
127   base::OneShotTimer delayed_show_timer_;
128 };
129 
130 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_
131