File: custom_help_bubble.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (139 lines) | stat: -rw-r--r-- 5,428 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_USER_EDUCATION_COMMON_HELP_BUBBLE_CUSTOM_HELP_BUBBLE_H_
#define COMPONENTS_USER_EDUCATION_COMMON_HELP_BUBBLE_CUSTOM_HELP_BUBBLE_H_

#include <concepts>

#include "base/callback_list.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/user_education/common/help_bubble/help_bubble.h"
#include "ui/base/interaction/element_tracker.h"

namespace user_education {

class CustomHelpBubbleViews;

// Custom Help Bubbles

// A custom help bubble is a `HelpBubble` that wraps some UI that behaves like a
// help bubble, but is not one of the help bubbles defined here in
// `components/user_education`.
//
// The UI of a custom help bubble should implement `CustomHelpBubbleUi`,
// which allows it to send the same signals back to the promo controller as
// normal help bubble UIs do.
//
// This UI should be wrapped in a `HelpBubble` object that also implements
// `CustomHelpBubble`, which allows access to the special interface. Common
// implementations that wrap e.g. Views bubble dialogs and WebUI dialogs will
// be provided.
//
// All of these requirements are enforced via template requirements.

// This is an interface that must be implemented by custom help bubble UIs (or
// their controllers). Custom help bubble UI should not close themselves in
// response to user input but instead notify the system via `NotifyUserAction()`
// with one of the `UserAction` values.
//
// These user actions are observed by the promo controller, which uses them to
// record usage data, emit histograms, and properly mark the promo as dismissed
// or snoozed.
//
// Custom bubbles may be closed due to UI changes outside the bubble, via the
// promo being canceled, or through calls like `NotifyPromoFeatureUsed()`,
// `CloseBubbleAndContinuePromo()`, etc. These will be handled by the promo
// controller, not the bubble itself.
class CustomHelpBubbleUi {
 public:
  // Subset of `FeaturePromoClosedReason` that indicates the user engaged with
  // the promo and the custom help bubble should close.
  //
  // A custom help bubble should not close itself, but rather, should notify one
  // of these user actions and then wait to be closed.
  enum class UserAction {
    // The user pressed a button like "Got it" or "No thanks". The bubble will
    // not be able to be shown again.
    //
    // This is differentiated from `kCancel` for metrics reasons - we want to
    // know if the user interacted with an action button or just reflexively
    // closed the bubble.
    kDismiss,

    // The user pressed a button like "Maybe later". This enables the help
    // bubble to be shown again at a later time.
    kSnooze,

    // The user pressed a button or link that did some action in the browser,
    // turned on a setting, etc.
    kAction,

    // The user pressed a default close button (X) or pressed ESC. All custom
    // UI that are not mandatory legal or privacy messaging should have an (X)
    // button and respond to ESC.
    //
    // This is differentiated from `kDismiss` for metrics reasons - we want to
    // know if the user interacted with an action button or just reflexively
    // closed the bubble.
    kCancel,
  };
  using UserActionCallback = base::OnceCallback<void(UserAction)>;

  CustomHelpBubbleUi();
  CustomHelpBubbleUi(CustomHelpBubbleUi& other) = delete;
  void operator=(CustomHelpBubbleUi& other) = delete;
  virtual ~CustomHelpBubbleUi();

  // Registers a callback to be invoked by the bubble (via `NotifyUserAction()`)
  // when something causes the bubble to want to close itself (eg. a click on a
  // Snooze button).
  //
  // The promo controller adds a callback when the bubble is registered,
  // responds to the callback by closing the bubble.
  base::CallbackListSubscription AddUserActionCallback(
      UserActionCallback callback);

  // Get this object as a weak pointer.
  base::WeakPtr<CustomHelpBubbleUi> GetCustomUiAsWeakPtr();

 protected:
  // Notifies listeners that the user has done some significant input which
  // should close the help bubble (such as clicking on "Snooze" button or on a
  // link). The promo controller will record the result and close the bubble.
  //
  // Be aware that `this` may not be valid after calling this method.
  void NotifyUserAction(UserAction user_action);

 private:
  friend class CustomHelpBubbleViews;

  std::unique_ptr<base::OnceCallbackList<void(UserAction)>>
      user_action_callbacks_;
  base::WeakPtrFactory<CustomHelpBubbleUi> weak_ptr_factory_{this};
};

// Add-on interface for `HelpBubble`s that wrap `CustomHelpBubbleUi`.
class CustomHelpBubble {
 public:
  explicit CustomHelpBubble(CustomHelpBubbleUi& bubble);
  virtual ~CustomHelpBubble();

  CustomHelpBubbleUi* custom_bubble_ui() { return bubble_.get(); }
  const CustomHelpBubbleUi* custom_bubble_ui() const { return bubble_.get(); }

 private:
  base::WeakPtr<CustomHelpBubbleUi> bubble_;
};

// A custom help bubble is both a `CustomHelpBubble` and a `HelpBubble`.
template <typename T>
concept IsCustomHelpBubble =
    std::derived_from<T, HelpBubble> && std::derived_from<T, CustomHelpBubble>;

}  // namespace user_education

#endif  // COMPONENTS_USER_EDUCATION_COMMON_HELP_BUBBLE_CUSTOM_HELP_BUBBLE_H_