help_bubble.cc 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2021 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/user_education/common/help_bubble.h"
  5. #include "base/auto_reset.h"
  6. #include "base/notreached.h"
  7. namespace user_education {
  8. HelpBubble::HelpBubble()
  9. : on_close_callbacks_(std::make_unique<CallbackList>()) {}
  10. HelpBubble::~HelpBubble() {
  11. // Derived classes must call Close() in destructor lest the bubble be
  12. // destroyed without cleaning up the framework-specific implementation. Since
  13. // Close() itself depends on framework-specific logic, however, it cannot be
  14. // called here, as virtual functions are no longer available in the base
  15. // destructor.
  16. CHECK(is_closed());
  17. }
  18. bool HelpBubble::Close() {
  19. // This prevents us from re-entrancy during CloseBubbleImpl() or after the
  20. // bubble is closed.
  21. if (is_closed() || closing_)
  22. return false;
  23. {
  24. // Prevent re-entrancy until is_closed() becomes true, which happens during
  25. // NotifyBubbleClosed().
  26. base::AutoReset<bool> closing_guard(&closing_, true);
  27. CloseBubbleImpl();
  28. }
  29. // This call could delete `this` so no code can come after it.
  30. NotifyBubbleClosed();
  31. return true;
  32. }
  33. void HelpBubble::OnAnchorBoundsChanged() {}
  34. gfx::Rect HelpBubble::GetBoundsInScreen() const {
  35. return gfx::Rect();
  36. }
  37. base::CallbackListSubscription HelpBubble::AddOnCloseCallback(
  38. ClosedCallback callback) {
  39. if (is_closed()) {
  40. NOTREACHED();
  41. return base::CallbackListSubscription();
  42. }
  43. return on_close_callbacks_->Add(std::move(callback));
  44. }
  45. void HelpBubble::NotifyBubbleClosed() {
  46. // We can't destruct the callback list during callbacks, so ensure that it
  47. // sticks around until the callbacks are all finished. This also has the side
  48. // effect of making is_closed() true since it resets the value of
  49. // `on_close_callbacks_`.
  50. std::unique_ptr<CallbackList> temp = std::move(on_close_callbacks_);
  51. if (temp)
  52. temp->Notify(this);
  53. }
  54. } // namespace user_education