summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
blob: 59e334ddc0084f10096e67b4210082f4a0b9b0d6 (plain)
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
225
226
227
228
229
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_
#define CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_

#include <memory>
#include <string>

#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/sync_startup_tracker.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/identity_manager/account_info.h"

class Browser;

namespace signin {
class IdentityManager;
}

namespace syncer {
class SyncService;
class SyncSetupInProgressHandle;
}

// Handles details of setting the primary account with IdentityManager and
// turning on sync for an account for which there is already a refresh token.
class DiceTurnSyncOnHelper : public SyncStartupTracker::Observer {
 public:
  // Behavior when the signin is aborted (by an error or cancelled by the user).
  enum class SigninAbortedMode {
    // The token is revoked and the account is signed out of the web.
    REMOVE_ACCOUNT,
    // The account is kept.
    KEEP_ACCOUNT
  };

  // User choice when signing in.
  // Used for UMA histograms, Hence, constants should never be deleted or
  // reordered, and  new constants should only be appended at the end.
  // Keep this in sync with SigninChoice in histograms.xml.
  enum SigninChoice {
    SIGNIN_CHOICE_CANCEL = 0,       // Signin is cancelled.
    SIGNIN_CHOICE_CONTINUE = 1,     // Signin continues in the current profile.
    SIGNIN_CHOICE_NEW_PROFILE = 2,  // Signin continues in a new profile.
    // SIGNIN_CHOICE_SIZE should always be last.
    SIGNIN_CHOICE_SIZE,
  };

  using SigninChoiceCallback = base::OnceCallback<void(SigninChoice)>;

  // Delegate implementing the UI prompts.
  class Delegate {
   public:
    virtual ~Delegate() {}

    // Shows a login error to the user.
    virtual void ShowLoginError(const std::string& email,
                                const std::string& error_message) = 0;

    // Shows a confirmation dialog when the user was previously signed in with a
    // different account in the same profile. |callback| must be called.
    virtual void ShowMergeSyncDataConfirmation(
        const std::string& previous_email,
        const std::string& new_email,
        SigninChoiceCallback callback) = 0;

    // Shows a confirmation dialog when the user is signing in a managed
    // account. |callback| must be called.
    virtual void ShowEnterpriseAccountConfirmation(
        const std::string& email,
        SigninChoiceCallback callback) = 0;

    // Shows a sync confirmation screen offering to open the Sync settings.
    // |callback| must be called.
    virtual void ShowSyncConfirmation(
        base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
            callback) = 0;

    // Opens the Sync settings page.
    virtual void ShowSyncSettings() = 0;

    // Informs the delegate that the flow is switching to a new profile.
    virtual void SwitchToProfile(Profile* new_profile) = 0;
  };

  // Create a helper that turns sync on for an account that is already present
  // in the token service.
  // |callback| is called at the end of the flow (i.e. after the user closes the
  // sync confirmation dialog).
  DiceTurnSyncOnHelper(Profile* profile,
                       signin_metrics::AccessPoint signin_access_point,
                       signin_metrics::PromoAction signin_promo_action,
                       signin_metrics::Reason signin_reason,
                       const std::string& account_id,
                       SigninAbortedMode signin_aborted_mode,
                       std::unique_ptr<Delegate> delegate,
                       base::OnceClosure callback);

  // Convenience constructor using the default delegate and empty callback.
  DiceTurnSyncOnHelper(Profile* profile,
                       Browser* browser,
                       signin_metrics::AccessPoint signin_access_point,
                       signin_metrics::PromoAction signin_promo_action,
                       signin_metrics::Reason signin_reason,
                       const std::string& account_id,
                       SigninAbortedMode signin_aborted_mode);

  // SyncStartupTracker::Observer:
  void SyncStartupCompleted() override;
  void SyncStartupFailed() override;

 private:
  friend class base::DeleteHelper<DiceTurnSyncOnHelper>;

  enum class ProfileMode {
    // Attempts to sign the user in |profile_|. Note that if the account to be
    // signed in is a managed account, then a profile confirmation dialog is
    // shown and the user has the possibility to create a new profile before
    // signing in.
    CURRENT_PROFILE,

    // Creates a new profile and signs the user in this new profile.
    NEW_PROFILE
  };

  // DiceTurnSyncOnHelper deletes itself.
  ~DiceTurnSyncOnHelper() override;

  // Handles can offer sign-in errors.  It returns true if there is an error,
  // and false otherwise.
  bool HasCanOfferSigninError();

  // Used as callback for ShowMergeSyncDataConfirmation().
  void OnMergeAccountConfirmation(SigninChoice choice);

  // Used as callback for ShowEnterpriseAccountConfirmation().
  void OnEnterpriseAccountConfirmation(SigninChoice choice);

  // Turns sync on with the current profile or a new profile.
  void TurnSyncOnWithProfileMode(ProfileMode profile_mode);

  // Callback invoked once policy registration is complete. If registration
  // fails, |dm_token| and |client_id| will be empty.
  void OnRegisteredForPolicy(const std::string& dm_token,
                             const std::string& client_id);

  // Helper function that loads policy with the cached |dm_token_| and
  // |client_id|, then completes the signin process.
  void LoadPolicyWithCachedCredentials();

  // Callback invoked when a policy fetch request has completed. |success| is
  // true if policy was successfully fetched.
  void OnPolicyFetchComplete(bool success);

  // Called to create a new profile, which is then signed in with the
  // in-progress auth credentials currently stored in this object.
  void CreateNewSignedInProfile();

  // Callback invoked once a profile is created, so we can transfer the
  // credentials.
  void OnNewProfileCreated(Profile* new_profile, Profile::CreateStatus status);

  // Callback invoked once the token service is ready for the new profile.
  void OnNewProfileTokensLoaded(Profile* new_profile);

  // Returns the SyncService, or nullptr if sync is not allowed.
  syncer::SyncService* GetSyncService();

  // Completes the signin in IdentityManager and displays the Sync confirmation
  // UI.
  void SigninAndShowSyncConfirmationUI();

  // Displays the Sync confirmation UI.
  // Note: If sync fails to start (e.g. sync is disabled by admin), the sync
  // confirmation dialog will be updated accordingly.
  void ShowSyncConfirmationUI();

  // Handles the user input from the sync confirmation UI and deletes this
  // object.
  void FinishSyncSetupAndDelete(
      LoginUIService::SyncConfirmationUIClosedResult result);

  // Switch to a new profile after exporting the token.
  void SwitchToProfile(Profile* new_profile);

  // Aborts the flow and deletes this object.
  void AbortAndDelete();

  std::unique_ptr<Delegate> delegate_;
  Profile* profile_;
  signin::IdentityManager* identity_manager_;
  const signin_metrics::AccessPoint signin_access_point_;
  const signin_metrics::PromoAction signin_promo_action_;
  const signin_metrics::Reason signin_reason_;

  // Whether the refresh token should be deleted if the Sync flow is aborted.
  SigninAbortedMode signin_aborted_mode_;

  // Account information.
  const AccountInfo account_info_;

  // Prevents Sync from running until configuration is complete.
  std::unique_ptr<syncer::SyncSetupInProgressHandle> sync_blocker_;

  // Policy credentials we keep while determining whether to create
  // a new profile for an enterprise user or not.
  std::string dm_token_;
  std::string client_id_;

  // Called when this object is deleted.
  base::ScopedClosureRunner scoped_callback_runner_;

  std::unique_ptr<SyncStartupTracker> sync_startup_tracker_;
  std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
      shutdown_subscription_;

  base::WeakPtrFactory<DiceTurnSyncOnHelper> weak_pointer_factory_{this};
  DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelper);
};

#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_