1 // Copyright 2018 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
5 #include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
6
7 #include "base/optional.h"
8 #include "components/prefs/pref_service.h"
9 #include "components/signin/internal/identity_manager/account_tracker_service.h"
10 #include "components/signin/internal/identity_manager/primary_account_manager.h"
11 #include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
12 #include "components/signin/public/base/device_id_helper.h"
13 #include "components/signin/public/base/signin_metrics.h"
14 #include "components/signin/public/identity_manager/account_info.h"
15 #include "google_apis/gaia/core_account_id.h"
16 #include "google_apis/gaia/gaia_constants.h"
17
18 namespace signin {
19
AccountsMutatorImpl(ProfileOAuth2TokenService * token_service,AccountTrackerService * account_tracker_service,PrimaryAccountManager * primary_account_manager,PrefService * pref_service)20 AccountsMutatorImpl::AccountsMutatorImpl(
21 ProfileOAuth2TokenService* token_service,
22 AccountTrackerService* account_tracker_service,
23 PrimaryAccountManager* primary_account_manager,
24 PrefService* pref_service)
25 : token_service_(token_service),
26 account_tracker_service_(account_tracker_service),
27 primary_account_manager_(primary_account_manager) {
28 DCHECK(token_service_);
29 DCHECK(account_tracker_service_);
30 DCHECK(primary_account_manager_);
31 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
32 pref_service_ = pref_service;
33 DCHECK(pref_service_);
34 #endif
35 }
36
~AccountsMutatorImpl()37 AccountsMutatorImpl::~AccountsMutatorImpl() {}
38
AddOrUpdateAccount(const std::string & gaia_id,const std::string & email,const std::string & refresh_token,bool is_under_advanced_protection,signin_metrics::SourceForRefreshTokenOperation source)39 CoreAccountId AccountsMutatorImpl::AddOrUpdateAccount(
40 const std::string& gaia_id,
41 const std::string& email,
42 const std::string& refresh_token,
43 bool is_under_advanced_protection,
44 signin_metrics::SourceForRefreshTokenOperation source) {
45 #if defined(OS_CHROMEOS)
46 NOTREACHED();
47 #endif
48 CoreAccountId account_id =
49 account_tracker_service_->SeedAccountInfo(gaia_id, email);
50 account_tracker_service_->SetIsAdvancedProtectionAccount(
51 account_id, is_under_advanced_protection);
52
53 // Flush the account changes to disk. Otherwise, in case of a browser crash,
54 // the account may be added to the token service but not to the account
55 // tracker, which is not intended.
56 account_tracker_service_->CommitPendingAccountChanges();
57
58 token_service_->UpdateCredentials(account_id, refresh_token, source);
59
60 return account_id;
61 }
62
UpdateAccountInfo(const CoreAccountId & account_id,base::Optional<bool> is_child_account,base::Optional<bool> is_under_advanced_protection)63 void AccountsMutatorImpl::UpdateAccountInfo(
64 const CoreAccountId& account_id,
65 base::Optional<bool> is_child_account,
66 base::Optional<bool> is_under_advanced_protection) {
67 if (is_child_account.has_value()) {
68 account_tracker_service_->SetIsChildAccount(account_id,
69 is_child_account.value());
70 }
71
72 if (is_under_advanced_protection.has_value()) {
73 account_tracker_service_->SetIsAdvancedProtectionAccount(
74 account_id, is_under_advanced_protection.value());
75 }
76 }
77
RemoveAccount(const CoreAccountId & account_id,signin_metrics::SourceForRefreshTokenOperation source)78 void AccountsMutatorImpl::RemoveAccount(
79 const CoreAccountId& account_id,
80 signin_metrics::SourceForRefreshTokenOperation source) {
81 #if defined(OS_CHROMEOS)
82 NOTREACHED();
83 #endif
84 token_service_->RevokeCredentials(account_id, source);
85 }
86
RemoveAllAccounts(signin_metrics::SourceForRefreshTokenOperation source)87 void AccountsMutatorImpl::RemoveAllAccounts(
88 signin_metrics::SourceForRefreshTokenOperation source) {
89 #if defined(OS_CHROMEOS)
90 NOTREACHED();
91 #endif
92 token_service_->RevokeAllCredentials(source);
93 }
94
InvalidateRefreshTokenForPrimaryAccount(signin_metrics::SourceForRefreshTokenOperation source)95 void AccountsMutatorImpl::InvalidateRefreshTokenForPrimaryAccount(
96 signin_metrics::SourceForRefreshTokenOperation source) {
97 #if defined(OS_CHROMEOS)
98 NOTREACHED();
99 #endif
100 DCHECK(primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync));
101 CoreAccountInfo primary_account_info =
102 primary_account_manager_->GetAuthenticatedAccountInfo();
103 AddOrUpdateAccount(primary_account_info.gaia, primary_account_info.email,
104 GaiaConstants::kInvalidRefreshToken,
105 primary_account_info.is_under_advanced_protection, source);
106 }
107
108 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
MoveAccount(AccountsMutator * target,const CoreAccountId & account_id)109 void AccountsMutatorImpl::MoveAccount(AccountsMutator* target,
110 const CoreAccountId& account_id) {
111 AccountInfo account_info =
112 account_tracker_service_->GetAccountInfo(account_id);
113 DCHECK(!account_info.account_id.empty());
114
115 auto* target_impl = static_cast<AccountsMutatorImpl*>(target);
116 target_impl->account_tracker_service_->SeedAccountInfo(account_info);
117 token_service_->ExtractCredentials(target_impl->token_service_, account_id);
118
119 // Reset the device ID from the source mutator: the exported token is linked
120 // to the device ID of the current mutator on the server. Reset the device ID
121 // of the current mutator to avoid tying it with the new mutator. See
122 // https://crbug.com/813928#c16
123 RecreateSigninScopedDeviceId(pref_service_);
124 }
125 #endif
126
127 } // namespace signin
128