Home | History | Annotate | Download | only in core
      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