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 (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars))
105 infobars_enabled_ = false;
108 InfoBarManager::~InfoBarManager() {}
110 void InfoBarManager::ShutDown() {
111 // Destroy all remaining InfoBars. It's important to not animate here so that
112 // we guarantee that we'll delete all delegates before we do anything else.
113 RemoveAllInfoBars(false);
114 FOR_EACH_OBSERVER(Observer, observer_list_, OnManagerShuttingDown(this));
117 void InfoBarManager::OnNavigation(
118 const InfoBarDelegate::NavigationDetails& details) {
119 // NOTE: It is not safe to change the following code to count upwards or
120 // use iterators, as the RemoveInfoBar() call synchronously modifies our
122 for (size_t i = infobars_.size(); i > 0; --i) {
123 InfoBar* infobar = infobars_[i - 1];
124 if (infobar->delegate()->ShouldExpire(details))
125 RemoveInfoBar(infobar);
129 void InfoBarManager::NotifyInfoBarAdded(InfoBar* infobar) {
130 FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar));
133 void InfoBarManager::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) {
134 FOR_EACH_OBSERVER(Observer, observer_list_,
135 OnInfoBarRemoved(infobar, animate));
138 void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
140 if (!infobars_enabled_) {
141 DCHECK(infobars_.empty());
145 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
146 DCHECK(i != infobars_.end());
148 // Remove the infobar before notifying, so that if any observers call back to
149 // AddInfoBar() or similar, we don't dupe-check against this infobar.
152 // This notification must happen before the call to CloseSoon() below, since
153 // observers may want to access |infobar| and that call can delete it.
154 NotifyInfoBarRemoved(infobar, animate);
156 infobar->CloseSoon();
159 } // namespace infobars