summaryrefslogtreecommitdiffstats
path: root/chrome/browser/infobars/infobar_container.h
blob: 896f112131cc28e4e75ce9ca643a28faa1218576 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_
#define CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_

#include <vector>

#include "base/compiler_specific.h"
#include "base/time.h"
#include "chrome/browser/ui/search/instant_overlay_model_observer.h"
#include "chrome/browser/ui/search/search_model_observer.h"
#include "chrome/common/search_types.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "third_party/skia/include/core/SkColor.h"

class InfoBar;
class InfoBarDelegate;
class InfoBarService;

namespace chrome {
namespace search {
class SearchModel;
}
}

// InfoBarContainer is a cross-platform base class to handle the visibility-
// related aspects of InfoBars.  While InfoBars own themselves, the
// InfoBarContainer is responsible for telling particular InfoBars that they
// should be hidden or visible.
//
// Platforms need to subclass this to implement a few platform-specific
// functions, which are pure virtual here.
//
// This class also observes changes to the SearchModel modes.  It hides infobars
// temporarily if the user changes into |SEARCH_SUGGESTIONS| mode (refer to
// chrome::search::Mode in chrome/common/search_types.h for all search modes)
// when on a :
// - |DEFAULT| page: when Instant overlay is ready;
// - |NTP| or |SEARCH_RESULTS| page: immediately;
//   TODO(kuan): this scenario requires more complex synchronization with
//   renderer SearchBoxAPI and will be implemented as the next step;
//   for now, hiding is immediate.
// When the user changes back out of |SEARCH_SUGGESTIONS| mode, it reshows any
// infobars, and starts a 50 ms window during which any attempts to re-hide any
// infobars are handled without animation.  This prevents glitchy-looking
// behavior when the user navigates following a mode change, which otherwise
// would re-show the infobars only to instantly animate them closed.  The window
// to re-hide infobars without animation is canceled if a tab change occurs.
class InfoBarContainer : public content::NotificationObserver,
                         public chrome::search::SearchModelObserver,
                         public InstantOverlayModelObserver {
 public:
  class Delegate {
   public:
    // The separator color may vary depending on where the container is hosted.
    virtual SkColor GetInfoBarSeparatorColor() const = 0;

    // The delegate is notified each time the infobar container changes height,
    // as well as when it stops animating.
    virtual void InfoBarContainerStateChanged(bool is_animating) = 0;

    // The delegate needs to tell us whether "unspoofable" arrows should be
    // drawn, and if so, at what |x| coordinate.  |x| may be NULL.
    virtual bool DrawInfoBarArrows(int* x) const = 0;

   protected:
    virtual ~Delegate();
  };

  // |search_model| may be NULL if this class is used in a window that does not
  // support Instant Extended.
  InfoBarContainer(Delegate* delegate,
                   chrome::search::SearchModel* search_model);
  virtual ~InfoBarContainer();

  // Changes the InfoBarService for which this container is showing
  // infobars.  This will remove all current infobars from the container, add
  // the infobars from |infobar_service|, and show them all.  |infobar_service|
  // may be NULL.
  void ChangeInfoBarService(InfoBarService* infobar_service);

  // Returns the amount by which to overlap the toolbar above, and, when
  // |total_height| is non-NULL, set it to the height of the InfoBarContainer
  // (including overlap).
  int GetVerticalOverlap(int* total_height);

  // Called by the delegate when the distance between what the top infobar's
  // "unspoofable" arrow would point to and the top infobar itself changes.
  // This enables the top infobar to show a longer arrow (e.g. because of a
  // visible bookmark bar) or shorter (e.g. due to being in a popup window) if
  // desired.
  //
  // IMPORTANT: This MUST NOT result in a call back to
  // Delegate::InfoBarContainerStateChanged() unless it causes an actual
  // change, lest we infinitely recurse.
  void SetMaxTopArrowHeight(int height);

  // Called when a contained infobar has animated or by some other means changed
  // its height, or when it stops animating.  The container is expected to do
  // anything necessary to respond, e.g. re-layout.
  void OnInfoBarStateChanged(bool is_animating);

  // Called by |infobar| to request that it be removed from the container, as it
  // is about to delete itself.  At this point, |infobar| should already be
  // hidden.
  void RemoveInfoBar(InfoBar* infobar);

  const Delegate* delegate() const { return delegate_; }

  // InstantOverlayModelObserver:
  virtual void OverlayStateChanged(const InstantOverlayModel& model) OVERRIDE;

 protected:
  // Subclasses must call this during destruction, so that we can remove
  // infobars (which will call the pure virtual functions below) while the
  // subclass portion of |this| has not yet been destroyed.
  void RemoveAllInfoBarsForDestruction();

  // These must be implemented on each platform to e.g. adjust the visible
  // object hierarchy.
  virtual void PlatformSpecificAddInfoBar(InfoBar* infobar,
                                          size_t position) = 0;
  virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) = 0;
  virtual void PlatformSpecificInfoBarStateChanged(bool is_animating) {}

 private:
  typedef std::vector<InfoBar*> InfoBars;

  // content::NotificationObserver:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // chrome::search::SearchModelObserver:
  virtual void ModeChanged(const chrome::search::Mode& old_mode,
                           const chrome::search::Mode& new_mode) OVERRIDE;

  // Hides an InfoBar for the specified delegate, in response to a notification
  // from the selected InfoBarService.  The InfoBar's disappearance will be
  // animated if |use_animation| is true and it has been more than 50ms since
  // infobars were reshown due to an Instant Extended mode change. The InfoBar
  // will call back to RemoveInfoBar() to remove itself once it's hidden (which
  // may mean synchronously).  Returns the position within |infobars_| the
  // infobar was previously at.
  size_t HideInfoBar(InfoBarDelegate* delegate, bool use_animation);

  // Hides all infobars in this container without animation.
  void HideAllInfoBars();

  // Adds |infobar| to this container before the existing infobar at position
  // |position| and calls Show() on it.  |animate| is passed along to
  // infobar->Show().  Depending on the value of |callback_status|, this calls
  // infobar->set_container(this) either before or after the call to Show() so
  // that OnInfoBarStateChanged() either will or won't be called as a result.
  enum CallbackStatus { NO_CALLBACK, WANT_CALLBACK };
  void AddInfoBar(InfoBar* infobar,
                  size_t position,
                  bool animate,
                  CallbackStatus callback_status);

  void UpdateInfoBarArrowTargetHeights();
  int ArrowTargetHeightForInfoBar(size_t infobar_index) const;

  content::NotificationRegistrar registrar_;
  Delegate* delegate_;
  InfoBarService* infobar_service_;
  InfoBars infobars_;

  // Tracks whether infobars in the container are shown or hidden.
  bool infobars_shown_;

  // Tracks the most recent time infobars were re-shown after being hidden due
  // to Instant Extended's ModeChanged.
  base::TimeTicks infobars_shown_time_;

  // Tracks which search mode is active, as well as mode changes, for Instant
  // Extended.
  chrome::search::SearchModel* search_model_;

  // Calculated in SetMaxTopArrowHeight().
  int top_arrow_target_height_;

  DISALLOW_COPY_AND_ASSIGN(InfoBarContainer);
};

#endif  // CHROME_BROWSER_INFOBARS_INFOBAR_CONTAINER_H_