| // Copyright 2018 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/ash/system/user_removal_manager.h" | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "base/functional/bind.h" | 
 | #include "base/functional/callback.h" | 
 | #include "base/location.h" | 
 | #include "base/logging.h" | 
 | #include "base/no_destructor.h" | 
 | #include "base/task/sequenced_task_runner.h" | 
 | #include "base/task/task_runner.h" | 
 | #include "base/time/time.h" | 
 | #include "chrome/browser/lifetime/application_lifetime.h" | 
 | #include "chrome/common/pref_names.h" | 
 | #include "components/prefs/persistent_pref_store.h" | 
 | #include "components/prefs/pref_service.h" | 
 | #include "components/user_manager/user.h" | 
 | #include "components/user_manager/user_manager.h" | 
 |  | 
 | namespace ash { | 
 | namespace user_removal_manager { | 
 |  | 
 | namespace { | 
 |  | 
 | // The time that InitiateUserRemoval waits on the passed callback to do a log | 
 | // out, otherwise it does the log out itself. | 
 | constexpr base::TimeDelta kFailsafeTimerTimeout = base::Seconds(60); | 
 |  | 
 | // Override for the LogOut function inside of tests. | 
 | base::OnceClosure& GetLogOutOverrideCallbackForTest() { | 
 |   static base::NoDestructor<base::OnceClosure> callback; | 
 |   return *callback; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | bool RemoveUsersIfNeeded(PrefService* local_state) { | 
 |   const PrefService::Preference* pref = | 
 |       local_state->FindPreference(prefs::kRemoveUsersRemoteCommand); | 
 |  | 
 |   if (pref->IsDefaultValue()) { | 
 |     // Nothing to be done. | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!pref->GetValue()->GetBool()) { | 
 |     LOG(ERROR) << "RemoveUsers started and did not finish. Chrome crashed?"; | 
 |     // Return to avoid crash loop. | 
 |     return false; | 
 |   } | 
 |  | 
 |   local_state->SetBoolean(prefs::kRemoveUsersRemoteCommand, false); | 
 |   local_state->CommitPendingWrite(); | 
 |   // TODO(https://crbug.com/1344832): Emit start metric here. | 
 |  | 
 |   user_manager::UserManager* user_manager = user_manager::UserManager::Get(); | 
 |   // Make a copy of the list since we'll be removing users (and the list would | 
 |   // change underneath us if we used a reference). | 
 |   const user_manager::UserList user_list = user_manager->GetPersistedUsers(); | 
 |  | 
 |   for (user_manager::User* user : user_list) { | 
 |     user_manager->RemoveUser( | 
 |         user->GetAccountId(), | 
 |         user_manager::UserRemovalReason::REMOTE_ADMIN_INITIATED); | 
 |   } | 
 |  | 
 |   // Revert to default value after removal is done. | 
 |   local_state->ClearPref(prefs::kRemoveUsersRemoteCommand); | 
 |  | 
 |   // TODO(https://crbug.com/1344832): Emit finish metric here. | 
 |   return true; | 
 | } | 
 |  | 
 | void LogOut() { | 
 |   auto& log_out_override_callback = GetLogOutOverrideCallbackForTest(); | 
 |   if (log_out_override_callback) { | 
 |     std::move(log_out_override_callback).Run(); | 
 |     return; | 
 |   } | 
 |   chrome::AttemptUserExit(); | 
 | } | 
 |  | 
 | void OverrideLogOutForTesting(base::OnceClosure callback) { | 
 |   auto& log_out_override_callback = GetLogOutOverrideCallbackForTest(); | 
 |   log_out_override_callback = std::move(callback); | 
 | } | 
 |  | 
 | void InitiateUserRemoval(PrefService* local_state, | 
 |                          base::OnceClosure on_pref_persisted_callback) { | 
 |   local_state->SetBoolean(prefs::kRemoveUsersRemoteCommand, true); | 
 |  | 
 |   local_state->CommitPendingWrite(base::BindOnce( | 
 |       [](base::OnceClosure on_pref_persisted_callback) { | 
 |         // Start the failsafe timer. | 
 |         base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( | 
 |             FROM_HERE, base::BindOnce(&LogOut), kFailsafeTimerTimeout); | 
 |  | 
 |         if (on_pref_persisted_callback) | 
 |           std::move(on_pref_persisted_callback).Run(); | 
 |       }, | 
 |       std::move(on_pref_persisted_callback))); | 
 | } | 
 |  | 
 | }  // namespace user_removal_manager | 
 | }  // namespace ash |