File: profile_management_flow_controller.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 (224 lines) | stat: -rw-r--r-- 8,778 bytes parent folder | download | duplicates (2)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_MANAGEMENT_FLOW_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_MANAGEMENT_FLOW_CONTROLLER_H_

#include <string>

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/timer/elapsed_timer.h"
#include "chrome/browser/ui/profiles/profile_picker.h"
#include "chrome/browser/ui/views/profiles/profile_management_types.h"
#include "chrome/browser/ui/views/profiles/profile_picker_web_contents_host.h"
#include "content/public/browser/web_contents.h"

class Profile;
class ProfileManagementStepController;
class ProfilePickerWebContentsHost;

// Represents an abstract user facing flow related to profile management.
//
// A profile management flow is made of a series of steps, implemented as
// `ProfileManagementStepController`s and owned by this object.
//
// Typical usage starts with calling `Init()` on the instantiated flow, which
// will register and switch to the first step. Then as the user interacts with
// the flow, this controller will handle instantiating and navigating between
// the next steps.
class ProfileManagementFlowController {
 public:
  // TODO(crbug.com/40237131): Split the steps more granularly across
  // logical steps instead of according to implementation details.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  // LINT.IfChange(Step)
  enum class Step {
    kUnknown = 0,
    // Renders the `chrome://profile-picker` app, covering the profile picker,
    // the profile type choice at the beginning of the profile creation
    // flow and the account selection.
    kProfilePicker = 1,
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
    // Renders the sign in screen on Dice platforms.
    kAccountSelection = 2,
    // Moves the rest of the flow to a browser tab so that the user can complete
    // the SAML sign in they started at the previous step.
    kFinishSamlSignin = 3,
    // Renders the reauth page.
    kReauth = 4,
#endif
    // Renders all post-sign in screens: enterprise management consent, profile
    // switch, sync opt-in, etc.
    kPostSignInFlow = 5,

    // Renders the beginning of the First Run Experience.
    kIntro = 6,

    // Renders a default browser promo.
    kDefaultBrowser = 7,

    // Renders the search engine choice screen.
    kSearchEngineChoice = 8,

    kFinishFlow = 9,

    kMaxValue = kFinishFlow,
  };
  // LINT.ThenChange(//tools/metrics/histograms/metadata/profile/enums.xml:ProfileManagementFlowStep)

  // Creates a flow controller that will start showing UI when `Init()`-ed.
  // `clear_host_callback` will be called if `host` needs to be closed.
  explicit ProfileManagementFlowController(ProfilePickerWebContentsHost* host,
                                           ClearHostClosure clear_host_callback,
                                           std::string_view flow_type_string);
  virtual ~ProfileManagementFlowController();

  // Starts the flow by registering and switching to the first step.
  virtual void Init() = 0;

  // Instructs a step registered as `step` to be shown.
  // If `step_switch_finished_callback` is provided, it will be called
  // with `true` when the navigation to `step` succeeded, or with
  // `false` otherwise.
  // Also see `ProfileManagementStepController::Show()`.
  void SwitchToStep(Step step,
                    bool reset_state,
                    StepSwitchFinishedCallback step_switch_finished_callback =
                        StepSwitchFinishedCallback(),
                    base::OnceClosure pop_step_callback = base::OnceClosure());

  void OnNavigateBackRequested();

#if BUILDFLAG(ENABLE_DICE_SUPPORT)
  void OnReloadRequested();
#endif

  // Cancel the signed-in profile setup and returns back to the main picker
  // screen (if the original EntryPoint was to open the picker).
  virtual void CancelPostSignInFlow() = 0;

  // Picks the profile with `profile_path`.
  // `pick_profile_complete_callback` will be called on profile load.
  virtual void PickProfile(
      const base::FilePath& profile_path,
      ProfilePicker::ProfilePickingArgs args,
      base::OnceCallback<void(bool)> pick_profile_complete_callback) = 0;

  // Clears the current state and reset it to the initial state that shows the
  // main screen. When calling this function the state should not be the
  // initial one. Executes `callback` when the initial state is shown.
  void Reset(StepSwitchFinishedCallback callback);

  // Returns a string to use as title for the window, for accessibility
  // purposes. It is used in case the host is not able to obtain a title from
  // the content it's rendering. As a final fallback, if this value is empty
  // (which is the default), the host will choose itself some generic title.
  virtual std::u16string GetFallbackAccessibleWindowTitle() const;

  // A helper method to create a pop callback that will switch to the given
  // step (can be used with `current_step()` to facilitate switching back to the
  // current active step).
  base::OnceClosure CreateSwitchToStepPopCallback(Step step);

 protected:
  void RegisterStep(
      Step step,
      std::unique_ptr<ProfileManagementStepController> step_controller);

  void UnregisterStep(Step step);

  bool IsStepInitialized(Step step) const;

  // Checks whether the flow has already attempted to exit.
  bool HasFlowExited() const;

  // Closes the flow, calling `clear_host_callback_`, which would cause the
  // `host()` to be deleted.
  void ExitFlow();

  // Opens a browser window for `profile`, closes the flow and then runs
  // `callback` (if it's non-null).
  //
  // Since the flow and its host will be destroyed by the time `callback` runs,
  // it should be longer lived than these.
  void FinishFlowAndRunInBrowser(Profile* profile,
                                 PostHostClearedCallback callback);

  // Will be called at the beginning of `FinishFlowAndRunInBrowser`.
  //
  // Subclasses should override it if they want to perform some additional
  // operations when the flow is closing. If they are going to open a browser
  // themselves, they should return `true`. The default implementation does
  // nothing and returns `false`.
  virtual bool PreFinishWithBrowser();

  Step current_step() const;

  ProfilePickerWebContentsHost* host() { return host_; }

  // Creates the web contents associated with `profile` and stores them in
  // `signed_out_flow_web_contents_`.
  void CreateSignedOutFlowWebContents(Profile* profile);

  // Returns a pointer to `signed_out_flow_web_contents_`.
  content::WebContents* GetSignedOutFlowWebContents() const;

 private:
  // Structure that takes care of logging metrics based on the flow type and the
  // input step.
  class FlowTracker {
   public:
    explicit FlowTracker(std::string_view flow_type_string);

    Step tracked_step() const { return tracked_step_; }

    // A new step was switched to; step started along with timer.
    void EnteredNewStep(Step step);
    // Step was either shown or skipped, if `success` is true, then the shown
    // timer is also started.
    void FinishedStepSwitch(Step step, bool success);
    // Current step was exited; stop all step timers and record corresponding
    // metrics.
    void ExitedCurrentStep();

    // Flow was exited during the current step.
    void ExitedFlow();

   private:
    const std::string flow_type_string_;

    // Step tracking.
    Step tracked_step_ = Step::kUnknown;
    std::optional<base::ElapsedTimer> step_start_elapsed_timer_;
    std::optional<base::ElapsedTimer> step_shown_elapsed_timer_;

    // Used to determine the total time spent in the flow.
    base::ElapsedTimer flow_elapsed_timer_;
  };

  // Called after a browser is open. Clears the host and then runs the callback.
  void CloseHostAndRunCallback(
      PostHostClearedCallback post_host_cleared_callback,
      Browser* browser);

  // The signed out flow web contents are used in some steps inside
  // `initialized_steps_`. They have to be destroyed after `initialized_steps_`.
  std::unique_ptr<content::WebContents> signed_out_flow_web_contents_;

  raw_ptr<ProfilePickerWebContentsHost> host_;
  ClearHostClosure clear_host_callback_;
  FlowTracker flow_tracker_;

  base::flat_map<Step, std::unique_ptr<ProfileManagementStepController>>
      initialized_steps_;

  base::WeakPtrFactory<ProfileManagementFlowController> weak_factory_{this};
};

std::string_view GetStepHistogramSuffixForTesting(
    ProfileManagementFlowController::Step step);

#endif  // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_MANAGEMENT_FLOW_CONTROLLER_H_