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 void InfoBarManager::Observer::OnInfoBarAdded(InfoBar
* infobar
) {
19 void InfoBarManager::Observer::OnInfoBarRemoved(InfoBar
* infobar
,
23 void InfoBarManager::Observer::OnInfoBarReplaced(InfoBar
* old_infobar
,
24 InfoBar
* new_infobar
) {
27 void InfoBarManager::Observer::OnManagerShuttingDown(InfoBarManager
* manager
) {
31 // InfoBarManager --------------------------------------------------------------
33 InfoBar
* InfoBarManager::AddInfoBar(scoped_ptr
<InfoBar
> infobar
) {
35 if (!infobars_enabled_
)
38 for (InfoBars::const_iterator
i(infobars_
.begin()); i
!= infobars_
.end();
40 if ((*i
)->delegate()->EqualsDelegate(infobar
->delegate())) {
41 DCHECK_NE((*i
)->delegate(), infobar
->delegate());
46 InfoBar
* infobar_ptr
= infobar
.release();
47 infobars_
.push_back(infobar_ptr
);
48 infobar_ptr
->SetOwner(this);
50 NotifyInfoBarAdded(infobar_ptr
);
55 void InfoBarManager::RemoveInfoBar(InfoBar
* infobar
) {
56 RemoveInfoBarInternal(infobar
, true);
59 void InfoBarManager::RemoveAllInfoBars(bool animate
) {
60 while (!infobars_
.empty())
61 RemoveInfoBarInternal(infobars_
.back(), animate
);
64 InfoBar
* InfoBarManager::ReplaceInfoBar(InfoBar
* old_infobar
,
65 scoped_ptr
<InfoBar
> new_infobar
) {
67 if (!infobars_enabled_
)
68 return AddInfoBar(new_infobar
.Pass()); // Deletes the infobar.
71 InfoBars::iterator
i(std::find(infobars_
.begin(), infobars_
.end(),
73 DCHECK(i
!= infobars_
.end());
75 InfoBar
* new_infobar_ptr
= new_infobar
.release();
76 i
= infobars_
.insert(i
, new_infobar_ptr
);
77 new_infobar_ptr
->SetOwner(this);
79 // Remove the old infobar before notifying, so that if any observers call back
80 // to AddInfoBar() or similar, we don't dupe-check against this infobar.
83 FOR_EACH_OBSERVER(Observer
,
85 OnInfoBarReplaced(old_infobar
, new_infobar_ptr
));
87 old_infobar
->CloseSoon();
88 return new_infobar_ptr
;
91 void InfoBarManager::AddObserver(Observer
* obs
) {
92 observer_list_
.AddObserver(obs
);
95 void InfoBarManager::RemoveObserver(Observer
* obs
) {
96 observer_list_
.RemoveObserver(obs
);
99 InfoBarManager::InfoBarManager()
100 : infobars_enabled_(true) {
101 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars
))
102 infobars_enabled_
= false;
105 InfoBarManager::~InfoBarManager() {}
107 void InfoBarManager::ShutDown() {
108 // Destroy all remaining InfoBars. It's important to not animate here so that
109 // we guarantee that we'll delete all delegates before we do anything else.
110 RemoveAllInfoBars(false);
111 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnManagerShuttingDown(this));
114 void InfoBarManager::OnNavigation(
115 const InfoBarDelegate::NavigationDetails
& details
) {
116 // NOTE: It is not safe to change the following code to count upwards or
117 // use iterators, as the RemoveInfoBar() call synchronously modifies our
119 for (size_t i
= infobars_
.size(); i
> 0; --i
) {
120 InfoBar
* infobar
= infobars_
[i
- 1];
121 if (infobar
->delegate()->ShouldExpire(details
))
122 RemoveInfoBar(infobar
);
126 void InfoBarManager::NotifyInfoBarAdded(InfoBar
* infobar
) {
127 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnInfoBarAdded(infobar
));
130 void InfoBarManager::NotifyInfoBarRemoved(InfoBar
* infobar
, bool animate
) {
131 FOR_EACH_OBSERVER(Observer
, observer_list_
,
132 OnInfoBarRemoved(infobar
, animate
));
135 void InfoBarManager::RemoveInfoBarInternal(InfoBar
* infobar
, bool animate
) {
137 if (!infobars_enabled_
) {
138 DCHECK(infobars_
.empty());
142 InfoBars::iterator
i(std::find(infobars_
.begin(), infobars_
.end(), infobar
));
143 DCHECK(i
!= infobars_
.end());
145 // Remove the infobar before notifying, so that if any observers call back to
146 // AddInfoBar() or similar, we don't dupe-check against this infobar.
149 // This notification must happen before the call to CloseSoon() below, since
150 // observers may want to access |infobar| and that call can delete it.
151 NotifyInfoBarRemoved(infobar
, animate
);
153 infobar
->CloseSoon();
156 } // namespace infobars