| 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 |