1 // Copyright 2019 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 #ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_INSTALLER_H_ 6 #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_INSTALLER_H_ 7 8 #include "base/callback_forward.h" 9 #include "base/macros.h" 10 #include "base/scoped_observer.h" 11 #include "chrome/browser/chromeos/crostini/ansible/ansible_management_service.h" 12 #include "chrome/browser/chromeos/crostini/crostini_installer_ui_delegate.h" 13 #include "chrome/browser/chromeos/crostini/crostini_manager.h" 14 #include "chrome/browser/chromeos/crostini/crostini_types.mojom-forward.h" 15 #include "components/keyed_service/core/keyed_service.h" 16 17 class Profile; 18 19 namespace base { 20 class RepeatingTimer; 21 } // namespace base 22 23 namespace crostini { 24 25 class CrostiniInstaller : public KeyedService, 26 public CrostiniManager::RestartObserver, 27 public CrostiniInstallerUIDelegate, 28 public AnsibleManagementService::Observer { 29 public: 30 // These values are persisted to logs. Entries should not be renumbered and 31 // numeric values should never be reused. 32 // When you add entries to this enum don't forget to update enums.xml and the 33 // plx scripts in 34 // https://plx.corp.google.com/home2/home/collections/c16e3c1474497b821 35 enum class SetupResult { 36 kNotStarted = 0, 37 // kUserCancelled = 1, 38 kSuccess = 2, 39 kErrorLoadingTermina = 3, 40 // kErrorStartingConcierge = 4, 41 kErrorCreatingDiskImage = 5, 42 kErrorStartingTermina = 6, 43 kErrorStartingContainer = 7, 44 kErrorOffline = 8, 45 kErrorFetchingSshKeys = 9, 46 kErrorMountingContainer = 10, 47 kErrorSettingUpContainer = 11, 48 49 kUserCancelledStart = 12, 50 kUserCancelledInstallImageLoader = 13, 51 // kUserCancelledStartConcierge = 14, 52 kUserCancelledCreateDiskImage = 15, 53 kUserCancelledStartTerminaVm = 16, 54 kUserCancelledCreateContainer = 17, 55 kUserCancelledStartContainer = 18, 56 kUserCancelledSetupContainer = 19, 57 kUserCancelledFetchSshKeys = 20, 58 kUserCancelledMountContainer = 21, 59 60 kErrorInsufficientDiskSpace = 22, 61 62 kErrorConfiguringContainer = 23, 63 kUserCancelledConfiguringContainer = 24, 64 65 kErrorCreateContainer = 25, 66 kErrorUnknown = 26, 67 68 kMaxValue = kErrorUnknown, 69 // When adding a new value, check you've followed the steps in the comment 70 // at the top of this enum. 71 }; 72 73 static CrostiniInstaller* GetForProfile(Profile* profile); 74 75 explicit CrostiniInstaller(Profile* profile); 76 ~CrostiniInstaller() override; 77 void Shutdown() override; 78 79 void ShowDialog(CrostiniUISurface ui_surface); 80 81 // CrostiniInstallerUIDelegate: 82 void Install(CrostiniManager::RestartOptions options, 83 ProgressCallback progress_callback, 84 ResultCallback result_callback) override; 85 void Cancel(base::OnceClosure callback) override; 86 void CancelBeforeStart() override; 87 88 // CrostiniManager::RestartObserver: 89 void OnStageStarted(crostini::mojom::InstallerState stage) override; 90 void OnComponentLoaded(crostini::CrostiniResult result) override; 91 void OnDiskImageCreated(bool success, 92 vm_tools::concierge::DiskImageStatus status, 93 int64_t disk_size_available) override; 94 void OnVmStarted(bool success) override; 95 void OnContainerDownloading(int32_t download_percent) override; 96 void OnContainerCreated(crostini::CrostiniResult result) override; 97 void OnContainerSetup(bool success) override; 98 void OnContainerStarted(crostini::CrostiniResult result) override; 99 void OnSshKeysFetched(bool success) override; 100 void OnContainerMounted(bool success) override; 101 102 // AnsibleManagementService::Observer: 103 void OnAnsibleSoftwareConfigurationStarted() override; 104 void OnAnsibleSoftwareConfigurationFinished(bool success) override; 105 106 // Return true if internal state allows starting installation. 107 bool CanInstall(); 108 set_require_cleanup_for_testing(bool require_cleanup)109 void set_require_cleanup_for_testing(bool require_cleanup) { 110 require_cleanup_ = require_cleanup; 111 } set_skip_launching_terminal_for_testing()112 void set_skip_launching_terminal_for_testing() { 113 skip_launching_terminal_for_testing_ = true; 114 } 115 116 private: 117 enum class State { 118 IDLE, 119 INSTALLING, 120 ERROR, // Something unexpected happened. 121 CANCEL_CLEANUP, // Deleting a partial installation. 122 CANCEL_ABORT_CHECK_DISK, // Don't proceed after checking disk. 123 }; 124 125 void RunProgressCallback(); 126 void UpdateState(State new_state); 127 void UpdateInstallingState( 128 crostini::mojom::InstallerState new_installing_state, 129 bool run_callback = true); 130 void HandleError(crostini::mojom::InstallerError error); 131 void FinishCleanup(crostini::CrostiniResult result); 132 void RecordSetupResult(SetupResult result); 133 134 void OnCrostiniRestartFinished(crostini::CrostiniResult result); 135 void OnAvailableDiskSpace(int64_t bytes); 136 137 void OnCrostiniRemovedAfterConfigurationFailed( 138 crostini::CrostiniResult result); 139 140 Profile* profile_; 141 142 State state_ = State::IDLE; 143 crostini::mojom::InstallerState installing_state_; 144 base::TimeTicks install_start_time_; 145 base::Time installing_state_start_time_; 146 base::RepeatingTimer state_progress_timer_; 147 bool require_cleanup_; 148 int64_t free_disk_space_; 149 int32_t container_download_percent_; 150 crostini::CrostiniManager::RestartId restart_id_ = 151 crostini::CrostiniManager::kUninitializedRestartId; 152 CrostiniManager::RestartOptions restart_options_; 153 154 bool skip_launching_terminal_for_testing_ = false; 155 156 ProgressCallback progress_callback_; 157 ResultCallback result_callback_; 158 base::OnceClosure cancel_callback_; 159 160 ScopedObserver<AnsibleManagementService, AnsibleManagementService::Observer> 161 ansible_management_service_observer_{this}; 162 163 base::WeakPtrFactory<CrostiniInstaller> weak_ptr_factory_{this}; 164 165 DISALLOW_COPY_AND_ASSIGN(CrostiniInstaller); 166 }; 167 168 } // namespace crostini 169 170 #endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_INSTALLER_H_ 171