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