| Index: chrome/browser/infobars/infobar_service.cc
 | 
| ===================================================================
 | 
| --- chrome/browser/infobars/infobar_service.cc	(revision 238220)
 | 
| +++ chrome/browser/infobars/infobar_service.cc	(working copy)
 | 
| @@ -16,8 +16,7 @@
 | 
|  
 | 
|  DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService);
 | 
|  
 | 
| -InfoBarDelegate* InfoBarService::AddInfoBar(
 | 
| -    scoped_ptr<InfoBarDelegate> infobar) {
 | 
| +InfoBar* InfoBarService::AddInfoBar(scoped_ptr<InfoBar> infobar) {
 | 
|    DCHECK(infobar);
 | 
|    if (!infobars_enabled_)
 | 
|      return NULL;
 | 
| @@ -24,16 +23,15 @@
 | 
|  
 | 
|    for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
 | 
|         ++i) {
 | 
| -    if ((*i)->EqualsDelegate(infobar.get())) {
 | 
| -      DCHECK_NE(*i, infobar.get());
 | 
| +    if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
 | 
| +      DCHECK_NE((*i)->delegate(), infobar->delegate());
 | 
|        return NULL;
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  InfoBarDelegate* infobar_ptr = infobar.release();
 | 
| +  InfoBar* infobar_ptr = infobar.release();
 | 
|    infobars_.push_back(infobar_ptr);
 | 
| -  // TODO(pkasting): Remove InfoBarService arg from delegate constructors and
 | 
| -  // instead use a setter from here.
 | 
| +  infobar_ptr->SetOwner(this);
 | 
|  
 | 
|    content::NotificationService::current()->Notify(
 | 
|        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
 | 
| @@ -42,16 +40,15 @@
 | 
|    return infobar_ptr;
 | 
|  }
 | 
|  
 | 
| -void InfoBarService::RemoveInfoBar(InfoBarDelegate* infobar) {
 | 
| +void InfoBarService::RemoveInfoBar(InfoBar* infobar) {
 | 
|    RemoveInfoBarInternal(infobar, true);
 | 
|  }
 | 
|  
 | 
| -InfoBarDelegate* InfoBarService::ReplaceInfoBar(
 | 
| -    InfoBarDelegate* old_infobar,
 | 
| -    scoped_ptr<InfoBarDelegate> new_infobar) {
 | 
| +InfoBar* InfoBarService::ReplaceInfoBar(InfoBar* old_infobar,
 | 
| +                                        scoped_ptr<InfoBar> new_infobar) {
 | 
|    DCHECK(old_infobar);
 | 
|    if (!infobars_enabled_)
 | 
| -    return AddInfoBar(new_infobar.Pass());  // Deletes the delegate.
 | 
| +    return AddInfoBar(new_infobar.Pass());  // Deletes the infobar.
 | 
|    DCHECK(new_infobar);
 | 
|  
 | 
|    InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
 | 
| @@ -58,19 +55,21 @@
 | 
|                                   old_infobar));
 | 
|    DCHECK(i != infobars_.end());
 | 
|  
 | 
| -  InfoBarDelegate* new_infobar_ptr = new_infobar.release();
 | 
| +  InfoBar* new_infobar_ptr = new_infobar.release();
 | 
|    i = infobars_.insert(i, new_infobar_ptr);
 | 
| +  new_infobar_ptr->SetOwner(this);
 | 
|    InfoBar::ReplacedDetails replaced_details(old_infobar, new_infobar_ptr);
 | 
|  
 | 
| -  // Remove the old infobar before notifying, so that if any observers call
 | 
| -  // back to AddInfoBar() or similar, we don't dupe-check against this infobar.
 | 
| +  // Remove the old infobar before notifying, so that if any observers call back
 | 
| +  // to AddInfoBar() or similar, we don't dupe-check against this infobar.
 | 
|    infobars_.erase(++i);
 | 
|  
 | 
| -  old_infobar->clear_owner();
 | 
|    content::NotificationService::current()->Notify(
 | 
|        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
 | 
|        content::Source<InfoBarService>(this),
 | 
|        content::Details<InfoBar::ReplacedDetails>(&replaced_details));
 | 
| +
 | 
| +  old_infobar->CloseSoon();
 | 
|    return new_infobar_ptr;
 | 
|  }
 | 
|  
 | 
| @@ -83,10 +82,6 @@
 | 
|  InfoBarService::~InfoBarService() {
 | 
|    // Destroy all remaining InfoBars.  It's important to not animate here so that
 | 
|    // we guarantee that we'll delete all delegates before we do anything else.
 | 
| -  //
 | 
| -  // TODO(pkasting): If there is no InfoBarContainer, this leaks all the
 | 
| -  // InfoBarDelegates.  This will be fixed once we call CloseSoon() directly on
 | 
| -  // Infobars.
 | 
|    RemoveAllInfoBars(false);
 | 
|  }
 | 
|  
 | 
| @@ -100,8 +95,8 @@
 | 
|    // use iterators, as the RemoveInfoBar() call synchronously modifies our
 | 
|    // delegate list.
 | 
|    for (size_t i = infobars_.size(); i > 0; --i) {
 | 
| -    InfoBarDelegate* infobar = infobars_[i - 1];
 | 
| -    if (infobar->ShouldExpire(load_details))
 | 
| +    InfoBar* infobar = infobars_[i - 1];
 | 
| +    if (infobar->delegate()->ShouldExpire(load_details))
 | 
|        RemoveInfoBar(infobar);
 | 
|    }
 | 
|  }
 | 
| @@ -127,8 +122,7 @@
 | 
|    return handled;
 | 
|  }
 | 
|  
 | 
| -void InfoBarService::RemoveInfoBarInternal(InfoBarDelegate* infobar,
 | 
| -                                           bool animate) {
 | 
| +void InfoBarService::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
 | 
|    DCHECK(infobar);
 | 
|    if (!infobars_enabled_) {
 | 
|      DCHECK(infobars_.empty());
 | 
| @@ -138,16 +132,19 @@
 | 
|    InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
 | 
|    DCHECK(i != infobars_.end());
 | 
|  
 | 
| -  infobar->clear_owner();
 | 
|    // Remove the infobar before notifying, so that if any observers call back to
 | 
|    // AddInfoBar() or similar, we don't dupe-check against this infobar.
 | 
|    infobars_.erase(i);
 | 
|  
 | 
| +  // This notification must happen before the call to CloseSoon() below, since
 | 
| +  // observers may want to access |infobar| and that call can delete it.
 | 
|    InfoBar::RemovedDetails removed_details(infobar, animate);
 | 
|    content::NotificationService::current()->Notify(
 | 
|        chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
 | 
|        content::Source<InfoBarService>(this),
 | 
|        content::Details<InfoBar::RemovedDetails>(&removed_details));
 | 
| +
 | 
| +  infobar->CloseSoon();
 | 
|  }
 | 
|  
 | 
|  void InfoBarService::RemoveAllInfoBars(bool animate) {
 | 
| 
 |