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 16 void InfoBarManager::Observer::OnInfoBarAdded(InfoBar* infobar) { 17 } 18 19 void InfoBarManager::Observer::OnInfoBarRemoved(InfoBar* infobar, 20 bool animate) { 21 } 22 23 void InfoBarManager::Observer::OnInfoBarReplaced(InfoBar* old_infobar, 24 InfoBar* new_infobar) { 25 } 26 27 void InfoBarManager::Observer::OnManagerShuttingDown(InfoBarManager* manager) { 28 } 29 30 31 // InfoBarManager -------------------------------------------------------------- 32 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 55 void InfoBarManager::RemoveInfoBar(InfoBar* infobar) { 56 RemoveInfoBarInternal(infobar, true); 57 } 58 59 void InfoBarManager::RemoveAllInfoBars(bool animate) { 60 while (!infobars_.empty()) 61 RemoveInfoBarInternal(infobars_.back(), animate); 62 } 63 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 91 void InfoBarManager::AddObserver(Observer* obs) { 92 observer_list_.AddObserver(obs); 93 } 94 95 void InfoBarManager::RemoveObserver(Observer* obs) { 96 observer_list_.RemoveObserver(obs); 97 } 98 99 InfoBarManager::InfoBarManager() 100 : infobars_enabled_(true) { 101 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars)) 102 infobars_enabled_ = false; 103 } 104 105 InfoBarManager::~InfoBarManager() {} 106 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 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 126 void InfoBarManager::NotifyInfoBarAdded(InfoBar* infobar) { 127 FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar)); 128 } 129 130 void InfoBarManager::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) { 131 FOR_EACH_OBSERVER(Observer, observer_list_, 132 OnInfoBarRemoved(infobar, animate)); 133 } 134 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