scoped_new_badge_tracker_base.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. #ifndef COMPONENTS_USER_EDUCATION_COMMON_SCOPED_NEW_BADGE_TRACKER_BASE_H_
  5. #define COMPONENTS_USER_EDUCATION_COMMON_SCOPED_NEW_BADGE_TRACKER_BASE_H_
  6. #include <set>
  7. #include "base/memory/raw_ptr.h"
  8. namespace base {
  9. struct Feature;
  10. }
  11. namespace feature_engagement {
  12. class Tracker;
  13. }
  14. namespace user_education {
  15. // Works with the Feature Engagement system to determine when/how many times a
  16. // New Badge is displayed to the user. Wraps a feature_engagement::Tracker so
  17. // the correct calls are made to the Feature Engagement backend.
  18. //
  19. // Derive a subclass for a more convenient constructor (e.g. one that takes a
  20. // Browser or Profile rather than a raw feature_engagement::Tracker).
  21. //
  22. // The lifespan of a ScopedNewBadgeTracker should match the time the dialog or
  23. // menu containing the New Badge is visible to the user.
  24. //
  25. // You may use a single tracker for New Badges on multiple features in the same
  26. // menu or dialog, but make sure the feature flags and event names are distinct.
  27. //
  28. // Usage:
  29. //
  30. // * Menus
  31. //
  32. // Below is an example of using a ScopedNewBadgeTracker to add a New Badge to a
  33. // menu where the object implementing ui::SimpleMenuModel::Delegate is created
  34. // each time the menu is shown (e.g. AppMenuModel, TabContextMenuContents,
  35. // etc.) The case where the delegate object is persistent will be discussed
  36. // later.
  37. //
  38. // // In OnMenuWillShow(menu):
  39. // menu->SetIsNewFeatureAt(
  40. // menu->GetIndexOfCommandId(IDC_MY_FEATURE).value(),
  41. // new_badge_tracker_.TryShowNewBadge(
  42. // feature_engagement::kIPHMyFeatureNewBadge,
  43. // &ui_features::kMyFeature));
  44. //
  45. // // In ExecuteCommand():
  46. // case IDC_MY_FEATURE:
  47. // new_badge_tracker_.EventPerformed("my_feature_activated");
  48. // ...
  49. // break;
  50. //
  51. // If the New Badge is in the top-level menu, you can move the call to
  52. // SetIsNewFeatureAt() to immediately after the menu model is initialized
  53. // (typically in the constructor or "Init" method) and you will not have to
  54. // override OnMenuWillBeShown().
  55. //
  56. // If you are handling multiple New Badges for different features, you will
  57. // want to check the result of GetIndexOfCommand() to make sure the menu being
  58. // shown is the one that contains the item receiving the new badge.
  59. //
  60. // If the ui::SimpleMenuModel::Delegate is a persistent object and is not
  61. // created each time the menu is displayed, you will need to move the tracker
  62. // down into the ui::SimpleMenuModel for your menu, and move your code from
  63. // OnMenuWillShow() to MenuWillShow() and from ExecuteCommand() to
  64. // ActivatedAt(int, int). Be sure to invoke base class behavior when overriding
  65. // these methods!
  66. //
  67. // * Dialogs
  68. //
  69. // Add a ScopedNewBadgeTracker member variable to your DialogDelegateView.
  70. // Dialogs are typically not re-usable; we create a new DialogDelegateView for
  71. // each time we show them. If you are following this pattern, include this in
  72. // your constructor or "Init" function after creating the NewBadgeLabel (but
  73. // before showing the dialog):
  74. //
  75. // new_badge_label_->SetDisplayNewBadge(
  76. // new_badge_tracker_.TryShowNewBadge(
  77. // feature_engagement::kIPHMyFeatureNewBadge,
  78. // &ui_features::kMyFeature));
  79. //
  80. // Then in the callback for the button that activates the feature being
  81. // promoted, call:
  82. //
  83. // new_badge_tracker_.EventPerformed("my_feature_activated");
  84. //
  85. // If for some reason you are re-using a dialog delegate, you must dynamically
  86. // create and destroy the tracker when the dialog is shown and hidden.
  87. class ScopedNewBadgeTrackerBase {
  88. public:
  89. // Constructs a scoped tracker for browser with |profile|.
  90. explicit ScopedNewBadgeTrackerBase(feature_engagement::Tracker* tracker);
  91. // This object should be destructed when the New Badge is going away, such as
  92. // when a menu with a New Badge or a dialog with a NewBadgeLabel is closing.
  93. // If TryShowNewBadge() returned true, the tracker will be informed that the
  94. // promo has ended.
  95. ~ScopedNewBadgeTrackerBase();
  96. ScopedNewBadgeTrackerBase(const ScopedNewBadgeTrackerBase& other) = delete;
  97. void operator=(const ScopedNewBadgeTrackerBase& other) = delete;
  98. // Returns whether the New Badge should be shown.
  99. //
  100. // |badge_feature| is the feature flag for the New Badge itself.
  101. //
  102. // |promoted_feature|, if specified, is the flag for the feature the New Badge
  103. // is promoting. You generally want to specify this feature even if the two
  104. // flags are controlled by the same Finch study, because the user could
  105. // override one but not the other. This parameter is optional because a New
  106. // Badge promo could be shown for a feature without a flag, or for a feature
  107. // that has already rolled to 100% and whose flag has been removed.
  108. bool TryShowNewBadge(const base::Feature& badge_feature,
  109. const base::Feature* promoted_feature = nullptr);
  110. // Indicates that the user performed a promoted action. |action_event_name|
  111. // should be the value referenced in the "event_used" parameter of your field
  112. // trial configuration.
  113. // Note: this is a wrapper around feature_engagement::Tracker::NotifyEvent().
  114. void ActionPerformed(const char* action_event_name);
  115. private:
  116. const raw_ptr<feature_engagement::Tracker> tracker_;
  117. std::set<const base::Feature*> active_badge_features_;
  118. };
  119. } // namespace user_education
  120. #endif // COMPONENTS_USER_EDUCATION_COMMON_SCOPED_NEW_BADGE_TRACKER_BASE_H_