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.
4
5 #include "components/infobars/core/infobar_manager.h"
6
7 #include "base/command_line.h"
8 #include "components/infobars/core/infobar.h"
9 #include "components/infobars/core/infobars_switches.h"
10
11 namespace infobars {
12
13
14 // InfoBarManager::Observer ---------------------------------------------------
15
OnInfoBarAdded(InfoBar * infobar)16 void InfoBarManager::Observer::OnInfoBarAdded(InfoBar* infobar) {
17 }
18
OnInfoBarRemoved(InfoBar * infobar,bool animate)19 void InfoBarManager::Observer::OnInfoBarRemoved(InfoBar* infobar,
20 bool animate) {
21 }
22
OnInfoBarReplaced(InfoBar * old_infobar,InfoBar * new_infobar)23 void InfoBarManager::Observer::OnInfoBarReplaced(InfoBar* old_infobar,
24 InfoBar* new_infobar) {
25 }
26
OnManagerShuttingDown(InfoBarManager * manager)27 void InfoBarManager::Observer::OnManagerShuttingDown(InfoBarManager* manager) {
28 }
29
30
31 // InfoBarManager --------------------------------------------------------------
32
AddInfoBar(scoped_ptr<InfoBar> infobar)33 InfoBar* InfoBarManager::AddInfoBar(scoped_ptr<InfoBar> infobar) {
34 DCHECK(infobar);
35 if (!infobars_enabled_)
36 return NULL;
37
38 for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
39 ++i) {
40 if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
41 DCHECK_NE((*i)->delegate(), infobar->delegate());
42 return NULL;
43 }
44 }
45
46 InfoBar* infobar_ptr = infobar.release();
47 infobars_.push_back(infobar_ptr);
48 infobar_ptr->SetOwner(this);
49
50 NotifyInfoBarAdded(infobar_ptr);
51
52 return infobar_ptr;
53 }
54
RemoveInfoBar(InfoBar * infobar)55 void InfoBarManager::RemoveInfoBar(InfoBar* infobar) {
56 RemoveInfoBarInternal(infobar, true);
57 }
58
RemoveAllInfoBars(bool animate)59 void InfoBarManager::RemoveAllInfoBars(bool animate) {
60 while (!infobars_.empty())
61 RemoveInfoBarInternal(infobars_.back(), animate);
62 }
63
ReplaceInfoBar(InfoBar * old_infobar,scoped_ptr<InfoBar> new_infobar)64 InfoBar* InfoBarManager::ReplaceInfoBar(InfoBar* old_infobar,
65 scoped_ptr<InfoBar> new_infobar) {
66 DCHECK(old_infobar);
67 if (!infobars_enabled_)
68 return AddInfoBar(new_infobar.Pass()); // Deletes the infobar.
69 DCHECK(new_infobar);
70
71 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
72 old_infobar));
73 DCHECK(i != infobars_.end());
74
75 InfoBar* new_infobar_ptr = new_infobar.release();
76 i = infobars_.insert(i, new_infobar_ptr);
77 new_infobar_ptr->SetOwner(this);
78
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.
81 infobars_.erase(++i);
82
83 FOR_EACH_OBSERVER(Observer,
84 observer_list_,
85 OnInfoBarReplaced(old_infobar, new_infobar_ptr));
86
87 old_infobar->CloseSoon();
88 return new_infobar_ptr;
89 }
90
AddObserver(Observer * obs)91 void InfoBarManager::AddObserver(Observer* obs) {
92 observer_list_.AddObserver(obs);
93 }
94
RemoveObserver(Observer * obs)95 void InfoBarManager::RemoveObserver(Observer* obs) {
96 observer_list_.RemoveObserver(obs);
97 }
98
InfoBarManager()99 InfoBarManager::InfoBarManager()
100 : infobars_enabled_(true) {
101 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars))
102 infobars_enabled_ = false;
103 }
104
~InfoBarManager()105 InfoBarManager::~InfoBarManager() {}
106
ShutDown()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));
112 }
113
OnNavigation(const InfoBarDelegate::NavigationDetails & details)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
118 // delegate list.
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);
123 }
124 }
125
NotifyInfoBarAdded(InfoBar * infobar)126 void InfoBarManager::NotifyInfoBarAdded(InfoBar* infobar) {
127 FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar));
128 }
129
NotifyInfoBarRemoved(InfoBar * infobar,bool animate)130 void InfoBarManager::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) {
131 FOR_EACH_OBSERVER(Observer, observer_list_,
132 OnInfoBarRemoved(infobar, animate));
133 }
134
RemoveInfoBarInternal(InfoBar * infobar,bool animate)135 void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
136 DCHECK(infobar);
137 if (!infobars_enabled_) {
138 DCHECK(infobars_.empty());
139 return;
140 }
141
142 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
143 DCHECK(i != infobars_.end());
144
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.
147 infobars_.erase(i);
148
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);
152
153 infobar->CloseSoon();
154 }
155
156 } // namespace infobars
157