OLD | NEW |
| (Empty) |
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 "chrome/browser/infobars/infobar_manager.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "chrome/browser/infobars/infobar.h" | |
9 #include "chrome/common/chrome_switches.h" | |
10 | |
11 InfoBar* InfoBarManager::AddInfoBar(scoped_ptr<InfoBar> infobar) { | |
12 DCHECK(infobar); | |
13 if (!infobars_enabled_) | |
14 return NULL; | |
15 | |
16 for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end(); | |
17 ++i) { | |
18 if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) { | |
19 DCHECK_NE((*i)->delegate(), infobar->delegate()); | |
20 return NULL; | |
21 } | |
22 } | |
23 | |
24 InfoBar* infobar_ptr = infobar.release(); | |
25 infobars_.push_back(infobar_ptr); | |
26 infobar_ptr->SetOwner(this); | |
27 | |
28 NotifyInfoBarAdded(infobar_ptr); | |
29 | |
30 return infobar_ptr; | |
31 } | |
32 | |
33 void InfoBarManager::RemoveInfoBar(InfoBar* infobar) { | |
34 RemoveInfoBarInternal(infobar, true); | |
35 } | |
36 | |
37 void InfoBarManager::RemoveAllInfoBars(bool animate) { | |
38 while (!infobars_.empty()) | |
39 RemoveInfoBarInternal(infobars_.back(), animate); | |
40 } | |
41 | |
42 InfoBar* InfoBarManager::ReplaceInfoBar(InfoBar* old_infobar, | |
43 scoped_ptr<InfoBar> new_infobar) { | |
44 DCHECK(old_infobar); | |
45 if (!infobars_enabled_) | |
46 return AddInfoBar(new_infobar.Pass()); // Deletes the infobar. | |
47 DCHECK(new_infobar); | |
48 | |
49 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), | |
50 old_infobar)); | |
51 DCHECK(i != infobars_.end()); | |
52 | |
53 InfoBar* new_infobar_ptr = new_infobar.release(); | |
54 i = infobars_.insert(i, new_infobar_ptr); | |
55 new_infobar_ptr->SetOwner(this); | |
56 | |
57 // Remove the old infobar before notifying, so that if any observers call back | |
58 // to AddInfoBar() or similar, we don't dupe-check against this infobar. | |
59 infobars_.erase(++i); | |
60 | |
61 NotifyInfoBarReplaced(old_infobar, new_infobar_ptr); | |
62 | |
63 old_infobar->CloseSoon(); | |
64 return new_infobar_ptr; | |
65 } | |
66 | |
67 void InfoBarManager::AddObserver(Observer* obs) { | |
68 observer_list_.AddObserver(obs); | |
69 } | |
70 | |
71 void InfoBarManager::RemoveObserver(Observer* obs) { | |
72 observer_list_.RemoveObserver(obs); | |
73 } | |
74 | |
75 InfoBarManager::InfoBarManager() | |
76 : infobars_enabled_(true) { | |
77 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars)) | |
78 infobars_enabled_ = false; | |
79 } | |
80 | |
81 InfoBarManager::~InfoBarManager() {} | |
82 | |
83 void InfoBarManager::ShutDown() { | |
84 // Destroy all remaining InfoBars. It's important to not animate here so that | |
85 // we guarantee that we'll delete all delegates before we do anything else. | |
86 RemoveAllInfoBars(false); | |
87 FOR_EACH_OBSERVER(Observer, observer_list_, OnManagerShuttingDown(this)); | |
88 } | |
89 | |
90 void InfoBarManager::OnNavigation( | |
91 const InfoBarDelegate::NavigationDetails& details) { | |
92 // NOTE: It is not safe to change the following code to count upwards or | |
93 // use iterators, as the RemoveInfoBar() call synchronously modifies our | |
94 // delegate list. | |
95 for (size_t i = infobars_.size(); i > 0; --i) { | |
96 InfoBar* infobar = infobars_[i - 1]; | |
97 if (infobar->delegate()->ShouldExpire(details)) | |
98 RemoveInfoBar(infobar); | |
99 } | |
100 } | |
101 | |
102 void InfoBarManager::NotifyInfoBarAdded(InfoBar* infobar) { | |
103 FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar)); | |
104 } | |
105 | |
106 void InfoBarManager::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) { | |
107 FOR_EACH_OBSERVER(Observer, observer_list_, | |
108 OnInfoBarRemoved(infobar, animate)); | |
109 } | |
110 | |
111 void InfoBarManager::NotifyInfoBarReplaced(InfoBar* old_infobar, | |
112 InfoBar* new_infobar) { | |
113 FOR_EACH_OBSERVER(Observer, | |
114 observer_list_, | |
115 OnInfoBarReplaced(old_infobar, new_infobar)); | |
116 } | |
117 | |
118 void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) { | |
119 DCHECK(infobar); | |
120 if (!infobars_enabled_) { | |
121 DCHECK(infobars_.empty()); | |
122 return; | |
123 } | |
124 | |
125 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar)); | |
126 DCHECK(i != infobars_.end()); | |
127 | |
128 // Remove the infobar before notifying, so that if any observers call back to | |
129 // AddInfoBar() or similar, we don't dupe-check against this infobar. | |
130 infobars_.erase(i); | |
131 | |
132 // This notification must happen before the call to CloseSoon() below, since | |
133 // observers may want to access |infobar| and that call can delete it. | |
134 NotifyInfoBarRemoved(infobar, animate); | |
135 | |
136 infobar->CloseSoon(); | |
137 } | |
OLD | NEW |