feature_promo_specification.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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_FEATURE_PROMO_SPECIFICATION_H_
  5. #define COMPONENTS_USER_EDUCATION_COMMON_FEATURE_PROMO_SPECIFICATION_H_
  6. #include <string>
  7. #include <vector>
  8. #include "base/callback_forward.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "components/user_education/common/help_bubble_params.h"
  11. #include "components/user_education/common/tutorial_identifier.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. #include "third_party/abseil-cpp/absl/types/variant.h"
  14. #include "ui/base/accelerators/accelerator.h"
  15. #include "ui/base/interaction/element_identifier.h"
  16. #include "ui/base/interaction/element_tracker.h"
  17. namespace base {
  18. struct Feature;
  19. }
  20. namespace gfx {
  21. struct VectorIcon;
  22. }
  23. namespace user_education {
  24. class FeaturePromoHandle;
  25. // Specifies the parameters for a feature promo and its associated bubble.
  26. class FeaturePromoSpecification {
  27. public:
  28. // The body text (specified by |bubble_body_string_id|) can have parameters
  29. // that can be specified situationally. When specifying these parameters,
  30. // use a |StringReplacements| object.
  31. using StringReplacements = std::vector<std::u16string>;
  32. // Optional method that filters a set of potential `elements` to choose and
  33. // return the anchor element, or null if none of the inputs is appropriate.
  34. // This method can return an element different from the input list, or null
  35. // if no valid element is found (this will cause the IPH not to run).
  36. using AnchorElementFilter = base::RepeatingCallback<ui::TrackedElement*(
  37. const ui::ElementTracker::ElementList& elements)>;
  38. // The callback type when creating a custom action IPH. The parameters are
  39. // `context`, which provides the context of the window in which the promo was
  40. // shown, and `promo_handle`, which holds the promo open until it is
  41. // destroyed.
  42. //
  43. // Typically, if you are taking an additional sequence of actions in response
  44. // to the custom callback, you will want to move `promo_handle` into longer-
  45. // term storage until that sequence is complete, to prevent additional IPH or
  46. // similar promos from being able to trigger in the interim. If you do not
  47. // care, simply let `promo_handle` expire at the end of the callback.
  48. using CustomActionCallback =
  49. base::RepeatingCallback<void(ui::ElementContext context,
  50. FeaturePromoHandle promo_handle)>;
  51. // Describes the type of promo. Used to configure defaults for the promo's
  52. // bubble.
  53. enum class PromoType {
  54. // Uninitialized/invalid specification.
  55. kUnspecifiied,
  56. // A toast-style promo.
  57. kToast,
  58. // A snooze-style promo.
  59. kSnooze,
  60. // A tutorial promo.
  61. kTutorial,
  62. // A promo where one button is replaced by a custom action.
  63. kCustomAction,
  64. // A simple promo that acts like a toast but without the required
  65. // accessibility data.
  66. kLegacy,
  67. };
  68. // Represents a command or command accelerator. Can be valueless (falsy) if
  69. // neither a command ID nor an explicit accelerator is specified.
  70. class AcceleratorInfo {
  71. public:
  72. // You can assign either an int (command ID) or a ui::Accelerator to an
  73. // AcceleratorInfo object.
  74. using ValueType = absl::variant<int, ui::Accelerator>;
  75. AcceleratorInfo();
  76. AcceleratorInfo(const AcceleratorInfo& other);
  77. ~AcceleratorInfo();
  78. explicit AcceleratorInfo(ValueType value);
  79. AcceleratorInfo& operator=(ValueType value);
  80. AcceleratorInfo& operator=(const AcceleratorInfo& other);
  81. explicit operator bool() const;
  82. bool operator!() const { return !static_cast<bool>(*this); }
  83. ui::Accelerator GetAccelerator(
  84. const ui::AcceleratorProvider* provider) const;
  85. private:
  86. ValueType value_;
  87. };
  88. struct DemoPageInfo {
  89. std::string display_title;
  90. std::string display_description;
  91. base::RepeatingClosure setup_for_feature_promo_callback;
  92. explicit DemoPageInfo(
  93. std::string display_title_ = std::string(),
  94. std::string display_description_ = std::string(),
  95. base::RepeatingClosure setup_for_feature_promo_callback_ =
  96. base::DoNothing());
  97. ~DemoPageInfo();
  98. DemoPageInfo(const DemoPageInfo& other);
  99. DemoPageInfo& operator=(const DemoPageInfo& other);
  100. };
  101. FeaturePromoSpecification();
  102. FeaturePromoSpecification(FeaturePromoSpecification&& other);
  103. ~FeaturePromoSpecification();
  104. FeaturePromoSpecification& operator=(FeaturePromoSpecification&& other);
  105. // Specifies a standard toast promo.
  106. // Because toasts are transient, they expect a separate screen reader prompt.
  107. // It is recommended that the prompt include an
  108. static FeaturePromoSpecification CreateForToastPromo(
  109. const base::Feature& feature,
  110. ui::ElementIdentifier anchor_element_id,
  111. int body_text_string_id,
  112. int accessible_text_string_id,
  113. AcceleratorInfo accessible_accelerator);
  114. // Specifies a promo with snooze buttons.
  115. static FeaturePromoSpecification CreateForSnoozePromo(
  116. const base::Feature& feature,
  117. ui::ElementIdentifier anchor_element_id,
  118. int body_text_string_id);
  119. // Specifies a promo that launches a tutorial.
  120. static FeaturePromoSpecification CreateForTutorialPromo(
  121. const base::Feature& feature,
  122. ui::ElementIdentifier anchor_element_id,
  123. int body_text_string_id,
  124. TutorialIdentifier tutorial_id);
  125. // Specifies a promo that triggers a custom action.
  126. static FeaturePromoSpecification CreateForCustomAction(
  127. const base::Feature& feature,
  128. ui::ElementIdentifier anchor_element_id,
  129. int body_text_string_id,
  130. int custom_action_string_id,
  131. CustomActionCallback custom_action_callback);
  132. // Specifies a text-only promo without additional accessibility information.
  133. // Deprecated. Only included for backwards compatibility with existing
  134. // promos. This is the only case in which |feature| can be null, and if it is
  135. // the result can only be used for a critical promo.
  136. static FeaturePromoSpecification CreateForLegacyPromo(
  137. const base::Feature* feature,
  138. ui::ElementIdentifier anchor_element_id,
  139. int body_text_string_id);
  140. // Set the optional bubble title. This text appears above the body text in a
  141. // slightly larger font.
  142. FeaturePromoSpecification& SetBubbleTitleText(int title_text_string_id);
  143. // Set the optional bubble icon. This is displayed next to the title or body
  144. // text.
  145. FeaturePromoSpecification& SetBubbleIcon(const gfx::VectorIcon* bubble_icon);
  146. // Set the bubble arrow. Default is top-left.
  147. FeaturePromoSpecification& SetBubbleArrow(HelpBubbleArrow bubble_arrow);
  148. // Set the anchor element filter.
  149. FeaturePromoSpecification& SetAnchorElementFilter(
  150. AnchorElementFilter anchor_element_filter);
  151. // Set whether we should look for the anchor element in any context.
  152. // Default is false. Since usually we only want to create the bubble in the
  153. // currently active window, this is only really useful for cases where there
  154. // is a floating window, WebContents, or tab-modal dialog that can become
  155. // detached from the current active window and therefore requires its own
  156. // unique context.
  157. FeaturePromoSpecification& SetInAnyContext(bool in_any_context);
  158. // Get the anchor element based on `anchor_element_id`,
  159. // `anchor_element_filter`, and `context`.
  160. ui::TrackedElement* GetAnchorElement(ui::ElementContext context) const;
  161. const base::Feature* feature() const { return feature_; }
  162. PromoType promo_type() const { return promo_type_; }
  163. ui::ElementIdentifier anchor_element_id() const { return anchor_element_id_; }
  164. const AnchorElementFilter& anchor_element_filter() const {
  165. return anchor_element_filter_;
  166. }
  167. bool in_any_context() const { return in_any_context_; }
  168. int bubble_body_string_id() const { return bubble_body_string_id_; }
  169. const std::u16string& bubble_title_text() const { return bubble_title_text_; }
  170. const gfx::VectorIcon* bubble_icon() const { return bubble_icon_; }
  171. HelpBubbleArrow bubble_arrow() const { return bubble_arrow_; }
  172. int screen_reader_string_id() const { return screen_reader_string_id_; }
  173. const AcceleratorInfo& screen_reader_accelerator() const {
  174. return screen_reader_accelerator_;
  175. }
  176. const DemoPageInfo& demo_page_info() const { return demo_page_info_; }
  177. FeaturePromoSpecification& SetDemoPageInfo(DemoPageInfo demo_page_info);
  178. const TutorialIdentifier& tutorial_id() const { return tutorial_id_; }
  179. const std::u16string custom_action_caption() const {
  180. return custom_action_caption_;
  181. }
  182. // Sets whether the custom action button is the default button on the help
  183. // bubble (default is false). It is an error to call this method for a promo
  184. // not created with CreateForCustomAction().
  185. FeaturePromoSpecification& SetCustomActionIsDefault(
  186. bool custom_action_is_default);
  187. bool custom_action_is_default() const { return custom_action_is_default_; }
  188. // Used to claim the callback when creating the bubble.
  189. CustomActionCallback custom_action_callback() const {
  190. return custom_action_callback_;
  191. }
  192. private:
  193. static constexpr HelpBubbleArrow kDefaultBubbleArrow =
  194. HelpBubbleArrow::kTopRight;
  195. FeaturePromoSpecification(const base::Feature* feature,
  196. PromoType promo_type,
  197. ui::ElementIdentifier anchor_element_id,
  198. int bubble_body_string_id);
  199. raw_ptr<const base::Feature> feature_ = nullptr;
  200. // The type of promo. A promo with type kUnspecified is not valid.
  201. PromoType promo_type_ = PromoType::kUnspecifiied;
  202. // The element identifier of the element to attach the promo to.
  203. ui::ElementIdentifier anchor_element_id_;
  204. // Whether we are allowed to search for the anchor element in any context.
  205. bool in_any_context_ = false;
  206. // The filter to use if there is more than one matching element, or
  207. // additional processing is needed (default is to always use the first
  208. // matching element).
  209. AnchorElementFilter anchor_element_filter_;
  210. // Text to be displayed in the promo bubble body. Should not be zero for
  211. // valid bubbles. We keep the string ID around because we can specify format
  212. // parameters when we actually create the bubble.
  213. int bubble_body_string_id_ = 0;
  214. // Optional text that is displayed at the top of the bubble, in a slightly
  215. // more prominent font.
  216. std::u16string bubble_title_text_;
  217. // Optional icon that is displayed next to bubble text.
  218. raw_ptr<const gfx::VectorIcon> bubble_icon_ = nullptr;
  219. // Optional arrow pointing to the promo'd element. Defaults to top left.
  220. HelpBubbleArrow bubble_arrow_ = kDefaultBubbleArrow;
  221. // Optional screen reader announcement that replaces bubble text when the
  222. // bubble is first announced.
  223. int screen_reader_string_id_ = 0;
  224. // Accelerator that is used to fill in a parametric field in
  225. // screen_reader_string_id_.
  226. AcceleratorInfo screen_reader_accelerator_;
  227. // Information to be displayed on the demo page
  228. DemoPageInfo demo_page_info_;
  229. // Tutorial identifier if the user decides to view a tutorial.
  230. TutorialIdentifier tutorial_id_;
  231. // Custom action button text.
  232. std::u16string custom_action_caption_;
  233. // Custom action button action.
  234. CustomActionCallback custom_action_callback_;
  235. // Whether the custom action is the default button.
  236. bool custom_action_is_default_ = false;
  237. };
  238. } // namespace user_education
  239. #endif // COMPONENTS_USER_EDUCATION_COMMON_FEATURE_PROMO_SPECIFICATION_H_