help_bubble_factory_registry.cc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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_factory_registry.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/callback_list.h"
  8. #include "base/no_destructor.h"
  9. #include "components/user_education/common/help_bubble.h"
  10. #include "components/user_education/common/help_bubble_factory.h"
  11. #include "components/user_education/common/help_bubble_params.h"
  12. #include "ui/base/interaction/element_identifier.h"
  13. #include "ui/base/interaction/element_tracker.h"
  14. namespace user_education {
  15. HelpBubbleFactoryRegistry::HelpBubbleFactoryRegistry() = default;
  16. HelpBubbleFactoryRegistry::~HelpBubbleFactoryRegistry() {
  17. for (auto& pr : help_bubbles_) {
  18. // Unsubscribe from the bubble before trying to close it so we don't try to
  19. // modify the map while we're iterating it.
  20. pr.second = base::CallbackListSubscription();
  21. pr.first->Close();
  22. }
  23. }
  24. std::unique_ptr<HelpBubble> HelpBubbleFactoryRegistry::CreateHelpBubble(
  25. ui::TrackedElement* element,
  26. HelpBubbleParams params) {
  27. CHECK(element);
  28. for (auto& bubble_factory : factories_) {
  29. if (bubble_factory.CanBuildBubbleForTrackedElement(element)) {
  30. auto result = bubble_factory.CreateBubble(element, std::move(params));
  31. if (result) {
  32. help_bubbles_.emplace(
  33. result.get(), result->AddOnCloseCallback(base::BindOnce(
  34. &HelpBubbleFactoryRegistry::OnHelpBubbleClosed,
  35. base::Unretained(this))));
  36. }
  37. return result;
  38. }
  39. }
  40. return nullptr;
  41. }
  42. void HelpBubbleFactoryRegistry::NotifyAnchorBoundsChanged(
  43. ui::ElementContext context) {
  44. for (const auto& pr : help_bubbles_) {
  45. if (pr.first->GetContext() == context)
  46. pr.first->OnAnchorBoundsChanged();
  47. }
  48. }
  49. bool HelpBubbleFactoryRegistry::ToggleFocusForAccessibility(
  50. ui::ElementContext context) {
  51. for (const auto& pr : help_bubbles_) {
  52. if (pr.first->GetContext() == context &&
  53. pr.first->ToggleFocusForAccessibility()) {
  54. toggle_focus_callbacks_.Notify(pr.first);
  55. return true;
  56. }
  57. }
  58. return false;
  59. }
  60. base::CallbackListSubscription
  61. HelpBubbleFactoryRegistry::AddToggleFocusCallback(
  62. ToggleFocusCallback callback) {
  63. return toggle_focus_callbacks_.Add(std::move(callback));
  64. }
  65. HelpBubble* HelpBubbleFactoryRegistry::GetHelpBubble(
  66. ui::ElementContext context) {
  67. for (const auto& pr : help_bubbles_) {
  68. if (pr.first->GetContext() == context)
  69. return pr.first;
  70. }
  71. return nullptr;
  72. }
  73. void HelpBubbleFactoryRegistry::OnHelpBubbleClosed(HelpBubble* bubble) {
  74. const auto result = help_bubbles_.erase(bubble);
  75. DCHECK(result);
  76. }
  77. } // namespace user_education