1 // Copyright 2014 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.
5 #include "components/infobars/core/infobar_manager.h"
7 #include "base/command_line.h"
8 #include "components/infobars/core/infobar.h"
9 #include "components/infobars/core/infobars_switches.h"
14 // InfoBarManager::Observer ---------------------------------------------------
16 InfoBarManager::Observer::~Observer() {
19 void InfoBarManager::Observer::OnInfoBarAdded(InfoBar
* infobar
) {
22 void InfoBarManager::Observer::OnInfoBarRemoved(InfoBar
* infobar
,
26 void InfoBarManager::Observer::OnInfoBarReplaced(InfoBar
* old_infobar
,
27 InfoBar
* new_infobar
) {
30 void InfoBarManager::Observer::OnManagerShuttingDown(InfoBarManager
* manager
) {
34 // InfoBarManager --------------------------------------------------------------
36 InfoBar
* InfoBarManager::AddInfoBar(scoped_ptr
<InfoBar
> infobar
) {
38 if (!infobars_enabled_
)
41 for (InfoBars::const_iterator
i(infobars_
.begin()); i
!= infobars_
.end();
43 if ((*i
)->delegate()->EqualsDelegate(infobar
->delegate())) {
44 DCHECK_NE((*i
)->delegate(), infobar
->delegate());
49 InfoBar
* infobar_ptr
= infobar
.release();
50 infobars_
.push_back(infobar_ptr
);
51 infobar_ptr
->SetOwner(this);
53 NotifyInfoBarAdded(infobar_ptr
);
58 void InfoBarManager::RemoveInfoBar(InfoBar
* infobar
) {
59 RemoveInfoBarInternal(infobar
, true);
62 void InfoBarManager::RemoveAllInfoBars(bool animate
) {
63 while (!infobars_
.empty())
64 RemoveInfoBarInternal(infobars_
.back(), animate
);
67 InfoBar
* InfoBarManager::ReplaceInfoBar(InfoBar
* old_infobar
,
68 scoped_ptr
<InfoBar
> new_infobar
) {
70 if (!infobars_enabled_
)
71 return AddInfoBar(new_infobar
.Pass()); // Deletes the infobar.
74 InfoBars::iterator
i(std::find(infobars_
.begin(), infobars_
.end(),
76 DCHECK(i
!= infobars_
.end());
78 InfoBar
* new_infobar_ptr
= new_infobar
.release();
79 i
= infobars_
.insert(i
, new_infobar_ptr
);
80 new_infobar_ptr
->SetOwner(this);
82 // Remove the old infobar before notifying, so that if any observers call back
83 // to AddInfoBar() or similar, we don't dupe-check against this infobar.
86 FOR_EACH_OBSERVER(Observer
,
88 OnInfoBarReplaced(old_infobar
, new_infobar_ptr
));
90 old_infobar
->CloseSoon();
91 return new_infobar_ptr
;
94 void InfoBarManager::AddObserver(Observer
* obs
) {
95 observer_list_
.AddObserver(obs
);
98 void InfoBarManager::RemoveObserver(Observer
* obs
) {
99 observer_list_
.RemoveObserver(obs
);
102 InfoBarManager::InfoBarManager()
103 : infobars_enabled_(true) {
104 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
105 switches::kDisableInfoBars
))
106 infobars_enabled_
= false;
109 InfoBarManager::~InfoBarManager() {}
111 void InfoBarManager::ShutDown() {
112 // Destroy all remaining InfoBars. It's important to not animate here so that
113 // we guarantee that we'll delete all delegates before we do anything else.
114 RemoveAllInfoBars(false);
115 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnManagerShuttingDown(this));
118 void InfoBarManager::OnNavigation(
119 const InfoBarDelegate::NavigationDetails
& details
) {
120 // NOTE: It is not safe to change the following code to count upwards or
121 // use iterators, as the RemoveInfoBar() call synchronously modifies our
123 for (size_t i
= infobars_
.size(); i
> 0; --i
) {
124 InfoBar
* infobar
= infobars_
[i
- 1];
125 if (infobar
->delegate()->ShouldExpire(details
))
126 RemoveInfoBar(infobar
);
130 void InfoBarManager::NotifyInfoBarAdded(InfoBar
* infobar
) {
131 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnInfoBarAdded(infobar
));
134 void InfoBarManager::NotifyInfoBarRemoved(InfoBar
* infobar
, bool animate
) {
135 FOR_EACH_OBSERVER(Observer
, observer_list_
,
136 OnInfoBarRemoved(infobar
, animate
));
139 void InfoBarManager::RemoveInfoBarInternal(InfoBar
* infobar
, bool animate
) {
141 if (!infobars_enabled_
) {
142 DCHECK(infobars_
.empty());
146 InfoBars::iterator
i(std::find(infobars_
.begin(), infobars_
.end(), infobar
));
147 DCHECK(i
!= infobars_
.end());
149 // Remove the infobar before notifying, so that if any observers call back to
150 // AddInfoBar() or similar, we don't dupe-check against this infobar.
153 // This notification must happen before the call to CloseSoon() below, since
154 // observers may want to access |infobar| and that call can delete it.
155 NotifyInfoBarRemoved(infobar
, animate
);
157 infobar
->CloseSoon();
160 } // namespace infobars