infobar_manager.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. #include "components/infobars/core/infobar_manager.h"
  5. #include <utility>
  6. #include "base/observer_list.h"
  7. #include "components/infobars/core/infobar.h"
  8. namespace infobars {
  9. // InfoBarManager::Observer ---------------------------------------------------
  10. InfoBarManager::Observer::~Observer() {
  11. }
  12. void InfoBarManager::Observer::OnInfoBarAdded(InfoBar* infobar) {
  13. }
  14. void InfoBarManager::Observer::OnInfoBarRemoved(InfoBar* infobar,
  15. bool animate) {
  16. }
  17. void InfoBarManager::Observer::OnInfoBarReplaced(InfoBar* old_infobar,
  18. InfoBar* new_infobar) {
  19. }
  20. void InfoBarManager::Observer::OnManagerShuttingDown(InfoBarManager* manager) {
  21. }
  22. // InfoBarManager --------------------------------------------------------------
  23. InfoBar* InfoBarManager::AddInfoBar(std::unique_ptr<InfoBar> infobar,
  24. bool replace_existing) {
  25. DCHECK(infobar);
  26. for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
  27. ++i) {
  28. if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
  29. DCHECK_NE((*i)->delegate(), infobar->delegate());
  30. return replace_existing ? ReplaceInfoBar(*i, std::move(infobar))
  31. : nullptr;
  32. }
  33. }
  34. InfoBar* infobar_ptr = infobar.release();
  35. infobars_.push_back(infobar_ptr);
  36. infobar_ptr->SetOwner(this);
  37. for (Observer& observer : observer_list_)
  38. observer.OnInfoBarAdded(infobar_ptr);
  39. return infobar_ptr;
  40. }
  41. void InfoBarManager::RemoveInfoBar(InfoBar* infobar) {
  42. RemoveInfoBarInternal(infobar, true);
  43. }
  44. void InfoBarManager::RemoveAllInfoBars(bool animate) {
  45. while (!infobars_.empty())
  46. RemoveInfoBarInternal(infobars_.back(), animate);
  47. }
  48. InfoBar* InfoBarManager::ReplaceInfoBar(InfoBar* old_infobar,
  49. std::unique_ptr<InfoBar> new_infobar) {
  50. DCHECK(old_infobar);
  51. DCHECK(new_infobar);
  52. auto i(std::find(infobars_.begin(), infobars_.end(), old_infobar));
  53. DCHECK(i != infobars_.end());
  54. InfoBar* new_infobar_ptr = new_infobar.release();
  55. i = infobars_.insert(i, new_infobar_ptr);
  56. new_infobar_ptr->SetOwner(this);
  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. for (Observer& observer : observer_list_)
  61. observer.OnInfoBarReplaced(old_infobar, new_infobar_ptr);
  62. old_infobar->CloseSoon();
  63. return new_infobar_ptr;
  64. }
  65. void InfoBarManager::AddObserver(Observer* obs) {
  66. observer_list_.AddObserver(obs);
  67. }
  68. void InfoBarManager::RemoveObserver(Observer* obs) {
  69. observer_list_.RemoveObserver(obs);
  70. }
  71. InfoBarManager::InfoBarManager() = default;
  72. InfoBarManager::~InfoBarManager() = default;
  73. void InfoBarManager::ShutDown() {
  74. // Destroy all remaining InfoBars. It's important to not animate here so that
  75. // we guarantee that we'll delete all delegates before we do anything else.
  76. RemoveAllInfoBars(false);
  77. for (Observer& observer : observer_list_)
  78. observer.OnManagerShuttingDown(this);
  79. }
  80. void InfoBarManager::OnNavigation(
  81. const InfoBarDelegate::NavigationDetails& details) {
  82. // NOTE: It is not safe to change the following code to count upwards or
  83. // use iterators, as the RemoveInfoBar() call synchronously modifies our
  84. // delegate list.
  85. for (size_t i = infobars_.size(); i > 0; --i) {
  86. InfoBar* infobar = infobars_[i - 1];
  87. if (infobar->delegate()->ShouldExpire(details))
  88. RemoveInfoBar(infobar);
  89. }
  90. }
  91. void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
  92. DCHECK(infobar);
  93. auto i(std::find(infobars_.begin(), infobars_.end(), infobar));
  94. // TODO(crbug.com/): Temporarily a CHECK instead of a DCHECK CHECK() in order
  95. // to help diagnose suspected memory smashing caused by invalid call of this
  96. // method happening in production code on iOS.
  97. CHECK(i != infobars_.end());
  98. // Remove the infobar before notifying, so that if any observers call back to
  99. // AddInfoBar() or similar, we don't dupe-check against this infobar.
  100. infobars_.erase(i);
  101. // This notification must happen before the call to CloseSoon() below, since
  102. // observers may want to access |infobar| and that call can delete it.
  103. for (Observer& observer : observer_list_)
  104. observer.OnInfoBarRemoved(infobar, animate);
  105. infobar->CloseSoon();
  106. }
  107. } // namespace infobars