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 #ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_MANAGER_H_ 6 #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_MANAGER_H_ 7 8 #include <map> 9 #include <string> 10 #include <utility> 11 #include <vector> 12 13 #include "base/files/file_path.h" 14 #include "base/memory/singleton.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/observer_list.h" 17 #include "base/optional.h" 18 #include "base/unguessable_token.h" 19 #include "chrome/browser/chromeos/crostini/crostini_simple_types.h" 20 #include "chrome/browser/chromeos/crostini/crostini_types.mojom-forward.h" 21 #include "chrome/browser/chromeos/crostini/crostini_util.h" 22 #include "chrome/browser/chromeos/crostini/termina_installer.h" 23 #include "chrome/browser/chromeos/vm_starting_observer.h" 24 #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" 25 #include "chrome/browser/ui/browser.h" 26 #include "chromeos/dbus/anomaly_detector/anomaly_detector.pb.h" 27 #include "chromeos/dbus/anomaly_detector_client.h" 28 #include "chromeos/dbus/cicerone/cicerone_service.pb.h" 29 #include "chromeos/dbus/cicerone_client.h" 30 #include "chromeos/dbus/concierge/concierge_service.pb.h" 31 #include "chromeos/dbus/concierge_client.h" 32 #include "chromeos/dbus/power/power_manager_client.h" 33 #include "chromeos/network/network_state.h" 34 #include "chromeos/network/network_state_handler.h" 35 #include "chromeos/network/network_state_handler_observer.h" 36 #include "components/keyed_service/core/keyed_service.h" 37 #include "services/device/public/mojom/usb_manager.mojom.h" 38 39 class Profile; 40 41 namespace crostini { 42 43 class CrostiniStabilityMonitor; 44 class CrostiniUpgradeAvailableNotification; 45 46 class LinuxPackageOperationProgressObserver { 47 public: 48 // A successfully started package install will continually fire progress 49 // events until it returns a status of SUCCEEDED or FAILED. The 50 // |progress_percent| field is given as a percentage of the given step, 51 // DOWNLOADING or INSTALLING. If |status| is FAILED, the |error_message| 52 // will contain output of the failing installation command. 53 virtual void OnInstallLinuxPackageProgress( 54 const ContainerId& container_id, 55 InstallLinuxPackageProgressStatus status, 56 int progress_percent, 57 const std::string& error_message) = 0; 58 59 // A successfully started package uninstall will continually fire progress 60 // events until it returns a status of SUCCEEDED or FAILED. 61 virtual void OnUninstallPackageProgress(const ContainerId& container_id, 62 UninstallPackageProgressStatus status, 63 int progress_percent) = 0; 64 }; 65 66 class PendingAppListUpdatesObserver : public base::CheckedObserver { 67 public: 68 // Called whenever the kPendingAppListUpdatesMethod signal is sent. 69 virtual void OnPendingAppListUpdates(const ContainerId& container_id, 70 int count) = 0; 71 }; 72 73 class ExportContainerProgressObserver { 74 public: 75 // DEPCRECATED. A successfully started container export will continually fire 76 // progress events until the original callback from ExportLxdContainer is 77 // invoked with a status of SUCCESS or CONTAINER_EXPORT_FAILED. 78 virtual void OnExportContainerProgress(const ContainerId& container_id, 79 ExportContainerProgressStatus status, 80 int progress_percent, 81 uint64_t progress_speed) = 0; 82 83 // A successfully started container export will continually fire progress 84 // events until the original callback from ExportLxdContainer is invoked with 85 // a status of SUCCESS or CONTAINER_EXPORT_FAILED. 86 virtual void OnExportContainerProgress(const ContainerId& container_id, 87 const StreamingExportStatus&) = 0; 88 }; 89 90 class ImportContainerProgressObserver { 91 public: 92 // A successfully started container import will continually fire progress 93 // events until the original callback from ImportLxdContainer is invoked with 94 // a status of SUCCESS or CONTAINER_IMPORT_FAILED[_*]. 95 virtual void OnImportContainerProgress( 96 const ContainerId& container_id, 97 ImportContainerProgressStatus status, 98 int progress_percent, 99 uint64_t progress_speed, 100 const std::string& architecture_device, 101 const std::string& architecture_container, 102 uint64_t available_space, 103 uint64_t minimum_required_space) = 0; 104 }; 105 106 class UpgradeContainerProgressObserver { 107 public: 108 virtual void OnUpgradeContainerProgress( 109 const ContainerId& container_id, 110 UpgradeContainerProgressStatus status, 111 const std::vector<std::string>& messages) = 0; 112 }; 113 114 class CrostiniDialogStatusObserver : public base::CheckedObserver { 115 public: 116 // Called when a Crostini dialog (installer, upgrader, etc.) opens or 117 // closes. 118 virtual void OnCrostiniDialogStatusChanged(DialogType dialog_type, 119 bool open) = 0; 120 }; 121 122 class CrostiniContainerPropertiesObserver : public base::CheckedObserver { 123 public: 124 // Called when a container's OS release version changes. 125 virtual void OnContainerOsReleaseChanged(const ContainerId& container_id, 126 bool can_upgrade) = 0; 127 }; 128 129 class VmShutdownObserver : public base::CheckedObserver { 130 public: 131 // Called when the given VM has shutdown. 132 virtual void OnVmShutdown(const std::string& vm_name) = 0; 133 }; 134 135 class ContainerStartedObserver : public base::CheckedObserver { 136 public: 137 // Called when the container has started. 138 virtual void OnContainerStarted(const ContainerId& container_id) = 0; 139 }; 140 141 class ContainerShutdownObserver : public base::CheckedObserver { 142 public: 143 // Called when the container has shutdown. 144 virtual void OnContainerShutdown(const ContainerId& container_id) = 0; 145 }; 146 147 class CrostiniMicSharingEnabledObserver : public base::CheckedObserver { 148 public: 149 // Called when changes are made to the Crostini mic settings. 150 virtual void OnCrostiniMicSharingEnabledChanged(bool enabled) = 0; 151 }; 152 153 class CrostiniFileChangeObserver : public base::CheckedObserver { 154 public: 155 // Called when a path registered via AddFileWatch() is changed. 156 virtual void OnCrostiniFileChanged(const ContainerId& container_id, 157 const base::FilePath& path) = 0; 158 }; 159 160 // CrostiniManager is a singleton which is used to check arguments for 161 // ConciergeClient and CiceroneClient. ConciergeClient is dedicated to 162 // communication with the Concierge service, CiceroneClient is dedicated to 163 // communication with the Cicerone service and both should remain as thin as 164 // possible. The existence of Cicerone is abstracted behind this class and 165 // only the Concierge name is exposed outside of here. 166 class CrostiniManager : public KeyedService, 167 public chromeos::AnomalyDetectorClient::Observer, 168 public chromeos::ConciergeClient::VmObserver, 169 public chromeos::ConciergeClient::ContainerObserver, 170 public chromeos::CiceroneClient::Observer, 171 public chromeos::NetworkStateHandlerObserver, 172 public chromeos::PowerManagerClient::Observer { 173 public: 174 using CrostiniResultCallback = 175 base::OnceCallback<void(CrostiniResult result)>; 176 using ExportLxdContainerResultCallback = 177 base::OnceCallback<void(CrostiniResult result, 178 uint64_t container_size, 179 uint64_t compressed_size)>; 180 // Callback indicating success or failure 181 using BoolCallback = base::OnceCallback<void(bool success)>; 182 183 using RestartId = int; 184 static const RestartId kUninitializedRestartId = -1; 185 186 // Observer class for the Crostini restart flow. 187 class RestartObserver { 188 public: ~RestartObserver()189 virtual ~RestartObserver() {} OnStageStarted(mojom::InstallerState stage)190 virtual void OnStageStarted(mojom::InstallerState stage) {} OnComponentLoaded(CrostiniResult result)191 virtual void OnComponentLoaded(CrostiniResult result) {} OnDiskImageCreated(bool success,vm_tools::concierge::DiskImageStatus status,int64_t disk_size_bytes)192 virtual void OnDiskImageCreated(bool success, 193 vm_tools::concierge::DiskImageStatus status, 194 int64_t disk_size_bytes) {} OnVmStarted(bool success)195 virtual void OnVmStarted(bool success) {} OnContainerDownloading(int32_t download_percent)196 virtual void OnContainerDownloading(int32_t download_percent) {} OnContainerCreated(CrostiniResult result)197 virtual void OnContainerCreated(CrostiniResult result) {} OnContainerSetup(bool success)198 virtual void OnContainerSetup(bool success) {} OnContainerStarted(CrostiniResult result)199 virtual void OnContainerStarted(CrostiniResult result) {} OnSshKeysFetched(bool success)200 virtual void OnSshKeysFetched(bool success) {} OnContainerMounted(bool success)201 virtual void OnContainerMounted(bool success) {} 202 restart_id()203 RestartId restart_id() const { return restart_id_; } 204 205 protected: 206 friend class CrostiniManager; set_restart_id(RestartId restart_id)207 void set_restart_id(RestartId restart_id) { restart_id_ = restart_id; } 208 RestartId restart_id_ = kUninitializedRestartId; 209 }; 210 211 struct RestartOptions { 212 // These two options only affect new containers. 213 base::Optional<std::string> container_username; 214 base::Optional<int64_t> disk_size_bytes; 215 216 RestartOptions(); 217 ~RestartOptions(); 218 // Add copy version if necessary. 219 RestartOptions(RestartOptions&&); 220 RestartOptions& operator=(RestartOptions&&); 221 }; 222 223 static CrostiniManager* GetForProfile(Profile* profile); 224 225 explicit CrostiniManager(Profile* profile); 226 ~CrostiniManager() override; 227 228 base::WeakPtr<CrostiniManager> GetWeakPtr(); 229 230 // Returns true if the /dev/kvm directory is present. 231 static bool IsDevKvmPresent(); 232 233 // Upgrades cros-termina component if the current version is not 234 // compatible. This is a no-op if chromeos::features::kCrostiniUseDlc is 235 // enabled. 236 void MaybeUpdateCrostini(); 237 238 // Installs termina using either component updater or the DLC service 239 // depending on the value of chromeos::features::kCrostiniUseDlc 240 void InstallTermina(CrostiniResultCallback callback); 241 242 // Unloads and removes termina. 243 void UninstallTermina(BoolCallback callback); 244 245 // Checks the arguments for creating a new Termina VM disk image. Creates a 246 // disk image for a Termina VM via ConciergeClient::CreateDiskImage. 247 // |callback| is called if the arguments are bad, or after the method call 248 // finishes. 249 using CreateDiskImageCallback = 250 base::OnceCallback<void(bool success, 251 vm_tools::concierge::DiskImageStatus, 252 const base::FilePath& disk_path)>; 253 void CreateDiskImage( 254 // The path to the disk image, including the name of 255 // the image itself. The image name should match the 256 // name of the VM that it will be used for. 257 const base::FilePath& disk_path, 258 // The storage location for the disk image 259 vm_tools::concierge::StorageLocation storage_location, 260 // The logical size of the disk image, in bytes 261 int64_t disk_size_bytes, 262 CreateDiskImageCallback callback); 263 264 // Checks the arguments for destroying a named Termina VM disk image. 265 // Removes the named Termina VM via ConciergeClient::DestroyDiskImage. 266 // |callback| is called if the arguments are bad, or after the method call 267 // finishes. 268 void DestroyDiskImage( 269 // The path to the disk image, including the name of the image itself. 270 const base::FilePath& disk_path, 271 BoolCallback callback); 272 273 using ListVmDisksCallback = 274 base::OnceCallback<void(CrostiniResult result, int64_t total_size)>; 275 void ListVmDisks(ListVmDisksCallback callback); 276 277 // Checks the arguments for starting a Termina VM. Starts a Termina VM via 278 // ConciergeClient::StartTerminaVm. |callback| is called if the arguments 279 // are bad, or after the method call finishes. 280 void StartTerminaVm( 281 // The human-readable name to be assigned to this VM. 282 std::string name, 283 // Path to the disk image on the host. 284 const base::FilePath& disk_path, 285 // The number of logical CPU cores that are currently disabled. 286 size_t num_cores_disabled, 287 BoolCallback callback); 288 289 // Checks the arguments for stopping a Termina VM. Stops the Termina VM via 290 // ConciergeClient::StopVm. |callback| is called if the arguments are bad, 291 // or after the method call finishes. 292 void StopVm(std::string name, CrostiniResultCallback callback); 293 294 // Asynchronously retrieve the Termina VM kernel version using 295 // concierge's GetVmEnterpriseReportingInfo method. 296 using GetTerminaVmKernelVersionCallback = base::OnceCallback<void( 297 const base::Optional<std::string>& maybe_kernel_version)>; 298 void GetTerminaVmKernelVersion(GetTerminaVmKernelVersionCallback callback); 299 300 // Wrapper for CiceroneClient::StartLxd with some extra parameter validation. 301 // |callback| is called immediately if the arguments are bad, or after LXD has 302 // been started. 303 void StartLxd(std::string vm_name, CrostiniResultCallback callback); 304 305 // Checks the arguments for creating an Lxd container via 306 // CiceroneClient::CreateLxdContainer. |callback| is called immediately if the 307 // arguments are bad, or once the container has been created. 308 void CreateLxdContainer(ContainerId container_id, 309 CrostiniResultCallback callback); 310 311 // Checks the arguments for deleting an Lxd container via 312 // CiceroneClient::DeleteLxdContainer. |callback| is called immediately if the 313 // arguments are bad, or once the container has been deleted. 314 void DeleteLxdContainer(ContainerId container_id, BoolCallback callback); 315 316 // Checks the arguments for starting an Lxd container via 317 // CiceroneClient::StartLxdContainer. |callback| is called immediately if the 318 // arguments are bad, or once the container has been created. 319 void StartLxdContainer(ContainerId container_id, 320 CrostiniResultCallback callback); 321 322 // Checks the arguments for setting up an Lxd container user via 323 // CiceroneClient::SetUpLxdContainerUser. |callback| is called immediately if 324 // the arguments are bad, or once garcon has been started. 325 void SetUpLxdContainerUser(ContainerId container_id, 326 std::string container_username, 327 BoolCallback callback); 328 329 // Checks the arguments for exporting an Lxd container via 330 // CiceroneClient::ExportLxdContainer. |callback| is called immediately if the 331 // arguments are bad, or after the method call finishes. 332 void ExportLxdContainer(ContainerId container_id, 333 base::FilePath export_path, 334 ExportLxdContainerResultCallback callback); 335 336 // Checks the arguments for importing an Lxd container via 337 // CiceroneClient::ImportLxdContainer. |callback| is called immediately if the 338 // arguments are bad, or after the method call finishes. 339 void ImportLxdContainer(ContainerId container_id, 340 base::FilePath import_path, 341 CrostiniResultCallback callback); 342 343 // Checks the arguments for cancelling a Lxd container export via 344 // CiceroneClient::CancelExportLxdContainer . 345 void CancelExportLxdContainer(ContainerId key); 346 347 // Checks the arguments for cancelling a Lxd container import via 348 // CiceroneClient::CancelImportLxdContainer. 349 void CancelImportLxdContainer(ContainerId key); 350 351 // Checks the arguments for upgrading an existing container via 352 // CiceroneClient::UpgradeContainer. An UpgradeProgressObserver should be used 353 // to monitor further results. 354 void UpgradeContainer(const ContainerId& key, 355 ContainerVersion source_version, 356 ContainerVersion target_version, 357 CrostiniResultCallback callback); 358 359 // Checks the arguments for canceling the upgrade of an existing container via 360 // CiceroneClient::CancelUpgradeContainer. 361 void CancelUpgradeContainer(const ContainerId& key, 362 CrostiniResultCallback callback); 363 364 // Asynchronously launches an app as specified by its desktop file id. 365 void LaunchContainerApplication(const ContainerId& container_id, 366 std::string desktop_file_id, 367 const std::vector<std::string>& files, 368 bool display_scaled, 369 CrostiniSuccessCallback callback); 370 371 // Asynchronously gets app icons as specified by their desktop file ids. 372 // |callback| is called after the method call finishes. 373 using GetContainerAppIconsCallback = 374 base::OnceCallback<void(bool success, const std::vector<Icon>& icons)>; 375 void GetContainerAppIcons(const ContainerId& container_id, 376 std::vector<std::string> desktop_file_ids, 377 int icon_size, 378 int scale, 379 GetContainerAppIconsCallback callback); 380 381 // Asynchronously retrieve information about a Linux Package (.deb) inside the 382 // container. 383 using GetLinuxPackageInfoCallback = 384 base::OnceCallback<void(const LinuxPackageInfo&)>; 385 void GetLinuxPackageInfo(const ContainerId& container_id, 386 std::string package_path, 387 GetLinuxPackageInfoCallback callback); 388 389 // Begin installation of a Linux Package inside the container. If the 390 // installation is successfully started, further updates will be sent to 391 // added LinuxPackageOperationProgressObservers. 392 using InstallLinuxPackageCallback = CrostiniResultCallback; 393 void InstallLinuxPackage(const ContainerId& container_id, 394 std::string package_path, 395 InstallLinuxPackageCallback callback); 396 397 // Begin installation of a Linux Package inside the container. If the 398 // installation is successfully started, further updates will be sent to 399 // added LinuxPackageOperationProgressObservers. Uses a package_id, given 400 // by "package_name;version;arch;data", to identify the package to install 401 // from the APT repository. 402 void InstallLinuxPackageFromApt(const ContainerId& container_id, 403 std::string package_id, 404 InstallLinuxPackageCallback callback); 405 406 // Begin uninstallation of a Linux Package inside the container. The package 407 // is identified by its associated .desktop file's ID; we don't use package_id 408 // to avoid problems with stale package_ids (such as after upgrades). If the 409 // uninstallation is successfully started, further updates will be sent to 410 // added LinuxPackageOperationProgressObservers. 411 void UninstallPackageOwningFile(const ContainerId& container_id, 412 std::string desktop_file_id, 413 CrostiniResultCallback callback); 414 415 // Asynchronously gets SSH server public key of container and trusted SSH 416 // client private key which can be used to connect to the container. 417 // |callback| is called after the method call finishes. 418 using GetContainerSshKeysCallback = 419 base::OnceCallback<void(bool success, 420 const std::string& container_public_key, 421 const std::string& host_private_key, 422 const std::string& hostname)>; 423 void GetContainerSshKeys(const ContainerId& container_id, 424 GetContainerSshKeysCallback callback); 425 426 // Add a relative path to watch within the container homedir. Register as a 427 // CrostiniFileChangeObserver to be notified when changes occur. Used by 428 // FilesApp. 429 void AddFileWatch(const ContainerId& container_id, 430 const base::FilePath& path, 431 BoolCallback callback); 432 void RemoveFileWatch(const ContainerId& container_id, 433 const base::FilePath& path); 434 void AddFileChangeObserver(CrostiniFileChangeObserver* observer); 435 void RemoveFileChangeObserver(CrostiniFileChangeObserver* observer); 436 437 // Lookup vsh session from pid. Used by terminal to open new tabs in cwd. 438 using VshSessionCallback = 439 base::OnceCallback<void(bool success, 440 const std::string& failure_reason, 441 int32_t container_shell_pid)>; 442 void GetVshSession(const ContainerId& container_id, 443 int32_t host_vsh_pid, 444 VshSessionCallback callback); 445 446 // Runs all the steps required to restart the given crostini vm and container. 447 // The optional |observer| tracks progress. If provided, it must be alive 448 // until the restart completes (i.e. when |callback| is called) or the restart 449 // is aborted via |AbortRestartCrostini|. 450 RestartId RestartCrostini(ContainerId container_id, 451 CrostiniResultCallback callback, 452 RestartObserver* observer = nullptr); 453 454 RestartId RestartCrostiniWithOptions(ContainerId container_id, 455 RestartOptions options, 456 CrostiniResultCallback callback, 457 RestartObserver* observer = nullptr); 458 459 // Aborts a restart. A "next" restarter with the same ContainerId will run, if 460 // there is one. |callback| will be called once the restart has finished 461 // aborting 462 void AbortRestartCrostini(RestartId restart_id, base::OnceClosure callback); 463 464 // Returns true if the Restart corresponding to |restart_id| is not yet 465 // complete. 466 bool IsRestartPending(RestartId restart_id); 467 468 // Adds a callback to receive notification of container shutdown. 469 void AddShutdownContainerCallback(ContainerId container_id, 470 base::OnceClosure shutdown_callback); 471 472 // Adds a callback to receive uninstall notification. 473 using RemoveCrostiniCallback = CrostiniResultCallback; 474 void AddRemoveCrostiniCallback(RemoveCrostiniCallback remove_callback); 475 476 // Add/remove observers for package install and uninstall progress. 477 void AddLinuxPackageOperationProgressObserver( 478 LinuxPackageOperationProgressObserver* observer); 479 void RemoveLinuxPackageOperationProgressObserver( 480 LinuxPackageOperationProgressObserver* observer); 481 482 // Add/remove observers for pending app list updates. 483 void AddPendingAppListUpdatesObserver( 484 PendingAppListUpdatesObserver* observer); 485 void RemovePendingAppListUpdatesObserver( 486 PendingAppListUpdatesObserver* observer); 487 488 // Add/remove observers for container export/import. 489 void AddExportContainerProgressObserver( 490 ExportContainerProgressObserver* observer); 491 void RemoveExportContainerProgressObserver( 492 ExportContainerProgressObserver* observer); 493 void AddImportContainerProgressObserver( 494 ImportContainerProgressObserver* observer); 495 void RemoveImportContainerProgressObserver( 496 ImportContainerProgressObserver* observer); 497 498 // Add/remove observers for container upgrade 499 void AddUpgradeContainerProgressObserver( 500 UpgradeContainerProgressObserver* observer); 501 void RemoveUpgradeContainerProgressObserver( 502 UpgradeContainerProgressObserver* observer); 503 504 // Add/remove vm shutdown observers. 505 void AddVmShutdownObserver(VmShutdownObserver* observer); 506 void RemoveVmShutdownObserver(VmShutdownObserver* observer); 507 508 // Add/remove vm starting observers. 509 void AddVmStartingObserver(chromeos::VmStartingObserver* observer); 510 void RemoveVmStartingObserver(chromeos::VmStartingObserver* observer); 511 512 // AnomalyDetectorClient::Observer: 513 void OnGuestFileCorruption( 514 const anomaly_detector::GuestFileCorruptionSignal& signal) override; 515 516 // ConciergeClient::VmObserver: 517 void OnVmStarted(const vm_tools::concierge::VmStartedSignal& signal) override; 518 void OnVmStopped(const vm_tools::concierge::VmStoppedSignal& signal) override; 519 520 // ConciergeClient::ContainerObserver: 521 void OnContainerStartupFailed( 522 const vm_tools::concierge::ContainerStartedSignal& signal) override; 523 524 // CiceroneClient::Observer: 525 void OnContainerStarted( 526 const vm_tools::cicerone::ContainerStartedSignal& signal) override; 527 void OnContainerShutdown( 528 const vm_tools::cicerone::ContainerShutdownSignal& signal) override; 529 void OnInstallLinuxPackageProgress( 530 const vm_tools::cicerone::InstallLinuxPackageProgressSignal& signal) 531 override; 532 void OnUninstallPackageProgress( 533 const vm_tools::cicerone::UninstallPackageProgressSignal& signal) 534 override; 535 void OnLxdContainerCreated( 536 const vm_tools::cicerone::LxdContainerCreatedSignal& signal) override; 537 void OnLxdContainerDeleted( 538 const vm_tools::cicerone::LxdContainerDeletedSignal& signal) override; 539 void OnLxdContainerDownloading( 540 const vm_tools::cicerone::LxdContainerDownloadingSignal& signal) override; 541 void OnTremplinStarted( 542 const vm_tools::cicerone::TremplinStartedSignal& signal) override; 543 void OnLxdContainerStarting( 544 const vm_tools::cicerone::LxdContainerStartingSignal& signal) override; 545 void OnExportLxdContainerProgress( 546 const vm_tools::cicerone::ExportLxdContainerProgressSignal& signal) 547 override; 548 void OnImportLxdContainerProgress( 549 const vm_tools::cicerone::ImportLxdContainerProgressSignal& signal) 550 override; 551 void OnPendingAppListUpdates( 552 const vm_tools::cicerone::PendingAppListUpdatesSignal& signal) override; 553 void OnApplyAnsiblePlaybookProgress( 554 const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal) 555 override; 556 void OnUpgradeContainerProgress( 557 const vm_tools::cicerone::UpgradeContainerProgressSignal& signal) 558 override; 559 void OnStartLxdProgress( 560 const vm_tools::cicerone::StartLxdProgressSignal& signal) override; 561 void OnFileWatchTriggered( 562 const vm_tools::cicerone::FileWatchTriggeredSignal& signal) override; 563 564 // chromeos::NetworkStateHandlerObserver overrides: 565 void ActiveNetworksChanged(const std::vector<const chromeos::NetworkState*>& 566 active_networks) override; 567 568 // chromeos::PowerManagerClient::Observer overrides: 569 void SuspendImminent(power_manager::SuspendImminent::Reason reason) override; 570 void SuspendDone(const base::TimeDelta& sleep_duration) override; 571 572 // Callback for |RemoveSshfsCrostiniVolume| called from |SuspendImminent| when 573 // the device is allowed to suspend. Removes metadata associated with the 574 // crostini sshfs mount and unblocks a pending suspend. 575 void OnRemoveSshfsCrostiniVolume( 576 base::UnguessableToken power_manager_suspend_token, 577 bool result); 578 579 void RemoveCrostini(std::string vm_name, RemoveCrostiniCallback callback); 580 581 void UpdateVmState(std::string vm_name, VmState vm_state); 582 bool IsVmRunning(std::string vm_name); 583 // Returns null if VM is not running. 584 base::Optional<VmInfo> GetVmInfo(std::string vm_name); 585 void AddRunningVmForTesting(std::string vm_name); 586 void AddStoppingVmForTesting(std::string vm_name); 587 588 void SetContainerSshfsMounted(const ContainerId& container_id, 589 bool is_mounted); 590 void SetContainerOsRelease(const ContainerId& container_id, 591 const vm_tools::cicerone::OsRelease& os_release); 592 const vm_tools::cicerone::OsRelease* GetContainerOsRelease( 593 const ContainerId& container_id) const; 594 // Returns null if VM or container is not running. 595 base::Optional<ContainerInfo> GetContainerInfo( 596 const ContainerId& container_id); 597 void AddRunningContainerForTesting(std::string vm_name, ContainerInfo info); 598 599 // If the Crostini reporting policy is set, save the last app launch 600 // time window and the Termina version in prefs for asynchronous reporting. 601 void UpdateLaunchMetricsForEnterpriseReporting(); 602 603 // Clear the lists of running VMs and containers. 604 // Can be called for testing to skip restart. set_skip_restart_for_testing()605 void set_skip_restart_for_testing() { skip_restart_for_testing_ = true; } skip_restart_for_testing()606 bool skip_restart_for_testing() { return skip_restart_for_testing_; } set_component_manager_load_error_for_testing(component_updater::CrOSComponentManager::Error error)607 void set_component_manager_load_error_for_testing( 608 component_updater::CrOSComponentManager::Error error) { 609 component_manager_load_error_for_testing_ = error; 610 } 611 612 void SetCrostiniDialogStatus(DialogType dialog_type, bool open); 613 // Returns true if the dialog is open. 614 bool GetCrostiniDialogStatus(DialogType dialog_type) const; 615 void AddCrostiniDialogStatusObserver(CrostiniDialogStatusObserver* observer); 616 void RemoveCrostiniDialogStatusObserver( 617 CrostiniDialogStatusObserver* observer); 618 619 void AddCrostiniContainerPropertiesObserver( 620 CrostiniContainerPropertiesObserver* observer); 621 void RemoveCrostiniContainerPropertiesObserver( 622 CrostiniContainerPropertiesObserver* observer); 623 624 void AddContainerStartedObserver(ContainerStartedObserver* observer); 625 void RemoveContainerStartedObserver(ContainerStartedObserver* observer); 626 void AddContainerShutdownObserver(ContainerShutdownObserver* observer); 627 void RemoveContainerShutdownObserver(ContainerShutdownObserver* observer); 628 629 void OnDBusShuttingDownForTesting(); 630 631 bool IsContainerUpgradeable(const ContainerId& container_id) const; 632 bool ShouldPromptContainerUpgrade(const ContainerId& container_id) const; 633 void UpgradePromptShown(const ContainerId& container_id); 634 void EnsureVmRunning(const ContainerId& key, CrostiniResultCallback callback); 635 bool IsUncleanStartup() const; 636 void SetUncleanStartupForTesting(bool is_unclean_startup); 637 void RemoveUncleanSshfsMounts(); 638 void DeallocateForwardedPortsCallback(Profile* profile, 639 const ContainerId& container_id); 640 641 void SetCrostiniMicSharingEnabled(bool enabled); crostini_mic_sharing_enabled()642 bool crostini_mic_sharing_enabled() const { 643 return crostini_mic_sharing_enabled_; 644 } 645 void AddCrostiniMicSharingEnabledObserver( 646 CrostiniMicSharingEnabledObserver* observer); 647 void RemoveCrostiniMicSharingEnabledObserver( 648 CrostiniMicSharingEnabledObserver* observer); 649 650 private: 651 class CrostiniRestarter; 652 653 void RemoveDBusObservers(); 654 655 // Callback for ConciergeClient::CreateDiskImage. Called after the Concierge 656 // service method finishes. 657 void OnCreateDiskImage( 658 CreateDiskImageCallback callback, 659 base::Optional<vm_tools::concierge::CreateDiskImageResponse> response); 660 661 // Callback for ConciergeClient::DestroyDiskImage. Called after the Concierge 662 // service method finishes. 663 void OnDestroyDiskImage( 664 BoolCallback callback, 665 base::Optional<vm_tools::concierge::DestroyDiskImageResponse> response); 666 667 // Callback for ConciergeClient::ListVmDisks. Called after the Concierge 668 // service method finishes. 669 void OnListVmDisks( 670 ListVmDisksCallback callback, 671 base::Optional<vm_tools::concierge::ListVmDisksResponse> response); 672 673 // Callback for ConciergeClient::StartTerminaVm. Called after the Concierge 674 // service method finishes. Updates running containers list then calls the 675 // |callback| if the container has already been started, otherwise passes the 676 // callback to OnStartTremplin. 677 void OnStartTerminaVm( 678 std::string vm_name, 679 BoolCallback callback, 680 base::Optional<vm_tools::concierge::StartVmResponse> response); 681 682 // Callback for ConciergeClient::TremplinStartedSignal. Called after the 683 // Tremplin service starts. Updates running containers list and then calls the 684 // |callback| with true, indicating success. 685 void OnStartTremplin(std::string vm_name, BoolCallback callback); 686 687 // Callback for ConciergeClient::StopVm. Called after the Concierge 688 // service method finishes. 689 void OnStopVm(std::string vm_name, 690 CrostiniResultCallback callback, 691 base::Optional<vm_tools::concierge::StopVmResponse> response); 692 693 // Callback for ConciergeClient::GetVmEnterpriseReportingInfo. 694 // Currently used to report the Termina kernel version for enterprise 695 // reporting. 696 void OnGetTerminaVmKernelVersion( 697 GetTerminaVmKernelVersionCallback callback, 698 base::Optional<vm_tools::concierge::GetVmEnterpriseReportingInfoResponse> 699 response); 700 701 // Callback for CiceroneClient::StartLxd. May indicate that LXD is still being 702 // started in which case we will wait for OnStartLxdProgress events. 703 void OnStartLxd( 704 std::string vm_name, 705 CrostiniResultCallback callback, 706 base::Optional<vm_tools::cicerone::StartLxdResponse> response); 707 708 // Callback for CiceroneClient::CreateLxdContainer. May indicate the container 709 // is still being created, in which case we will wait for an 710 // OnLxdContainerCreated event. 711 void OnCreateLxdContainer( 712 const ContainerId& container_id, 713 CrostiniResultCallback callback, 714 base::Optional<vm_tools::cicerone::CreateLxdContainerResponse> response); 715 716 // Callback for CiceroneClient::DeleteLxdContainer. 717 void OnDeleteLxdContainer( 718 const ContainerId& container_id, 719 BoolCallback callback, 720 base::Optional<vm_tools::cicerone::DeleteLxdContainerResponse> response); 721 722 // Callback for CiceroneClient::StartLxdContainer. 723 void OnStartLxdContainer( 724 const ContainerId& container_id, 725 CrostiniResultCallback callback, 726 base::Optional<vm_tools::cicerone::StartLxdContainerResponse> response); 727 728 // Callback for CiceroneClient::SetUpLxdContainerUser. 729 void OnSetUpLxdContainerUser( 730 const ContainerId& container_id, 731 BoolCallback callback, 732 base::Optional<vm_tools::cicerone::SetUpLxdContainerUserResponse> 733 response); 734 735 // Callback for CiceroneClient::ExportLxdContainer. 736 void OnExportLxdContainer( 737 const ContainerId& container_id, 738 base::Optional<vm_tools::cicerone::ExportLxdContainerResponse> response); 739 740 // Callback for CiceroneClient::ImportLxdContainer. 741 void OnImportLxdContainer( 742 const ContainerId& container_id, 743 base::Optional<vm_tools::cicerone::ImportLxdContainerResponse> response); 744 745 // Callback for CiceroneClient::CancelExportLxdContainer. 746 void OnCancelExportLxdContainer( 747 const ContainerId& key, 748 base::Optional<vm_tools::cicerone::CancelExportLxdContainerResponse> 749 response); 750 751 // Callback for CiceroneClient::CancelImportLxdContainer. 752 void OnCancelImportLxdContainer( 753 const ContainerId& key, 754 base::Optional<vm_tools::cicerone::CancelImportLxdContainerResponse> 755 response); 756 757 // Callback for CiceroneClient::UpgradeContainer. 758 void OnUpgradeContainer( 759 CrostiniResultCallback callback, 760 base::Optional<vm_tools::cicerone::UpgradeContainerResponse> response); 761 762 // Callback for CiceroneClient::CancelUpgradeContainer. 763 void OnCancelUpgradeContainer( 764 CrostiniResultCallback callback, 765 base::Optional<vm_tools::cicerone::CancelUpgradeContainerResponse> 766 response); 767 768 // Callback for CrostiniManager::LaunchContainerApplication. 769 void OnLaunchContainerApplication( 770 CrostiniSuccessCallback callback, 771 base::Optional<vm_tools::cicerone::LaunchContainerApplicationResponse> 772 response); 773 774 // Callback for CrostiniManager::GetContainerAppIcons. Called after the 775 // Concierge service finishes. 776 void OnGetContainerAppIcons( 777 GetContainerAppIconsCallback callback, 778 base::Optional<vm_tools::cicerone::ContainerAppIconResponse> response); 779 780 // Callback for CrostiniManager::GetLinuxPackageInfo. 781 void OnGetLinuxPackageInfo( 782 GetLinuxPackageInfoCallback callback, 783 base::Optional<vm_tools::cicerone::LinuxPackageInfoResponse> response); 784 785 // Callback for CrostiniManager::InstallLinuxPackage. 786 void OnInstallLinuxPackage( 787 InstallLinuxPackageCallback callback, 788 base::Optional<vm_tools::cicerone::InstallLinuxPackageResponse> response); 789 790 // Callback for CrostiniManager::UninstallPackageOwningFile. 791 void OnUninstallPackageOwningFile( 792 CrostiniResultCallback callback, 793 base::Optional<vm_tools::cicerone::UninstallPackageOwningFileResponse> 794 response); 795 796 // Callback for CrostiniManager::GetContainerSshKeys. Called after the 797 // Concierge service finishes. 798 void OnGetContainerSshKeys( 799 GetContainerSshKeysCallback callback, 800 base::Optional<vm_tools::concierge::ContainerSshKeysResponse> response); 801 802 // Callback for AnsibleManagementService::ConfigureDefaultContainer 803 void OnDefaultContainerConfigured(bool success); 804 805 // Helper for CrostiniManager::MaybeUpdateCrostini. Makes blocking calls to 806 // check for /dev/kvm. 807 static void CheckPaths(); 808 809 // Helper for CrostiniManager::MaybeUpdateCrostini. Separated because the 810 // checking component registration code may block. 811 void MaybeUpdateCrostiniAfterChecks(); 812 813 void FinishRestart(CrostiniRestarter* restarter, CrostiniResult result); 814 815 // Callback for CrostiniManager::AbortRestartCrostini 816 void OnAbortRestartCrostini(RestartId restart_id, base::OnceClosure callback); 817 818 // Callback for CrostiniManager::RemoveCrostini. 819 void OnRemoveCrostini(CrostiniResult result); 820 821 void OnVmStoppedCleanup(const std::string& vm_name); 822 823 // Configure the container so that it can sideload apps into Arc++. 824 void ConfigureForArcSideload(); 825 826 // Tries to query Concierge for the type of disk the named VM has then emits a 827 // metric logging the type. Mostly happens async and best-effort. 828 void EmitVmDiskTypeMetric(const std::string vm_name); 829 830 Profile* profile_; 831 std::string owner_id_; 832 833 bool skip_restart_for_testing_ = false; 834 component_updater::CrOSComponentManager::Error 835 component_manager_load_error_for_testing_ = 836 component_updater::CrOSComponentManager::Error::NONE; 837 838 static bool is_dev_kvm_present_; 839 840 // |is_unclean_startup_| is true when we detect Concierge still running at 841 // session startup time, and the last session ended in a crash. 842 bool is_unclean_startup_ = false; 843 844 // Callbacks that are waiting on a signal 845 std::multimap<ContainerId, CrostiniResultCallback> start_container_callbacks_; 846 std::multimap<ContainerId, base::OnceClosure> shutdown_container_callbacks_; 847 std::multimap<ContainerId, CrostiniResultCallback> 848 create_lxd_container_callbacks_; 849 std::multimap<ContainerId, BoolCallback> delete_lxd_container_callbacks_; 850 std::map<ContainerId, ExportLxdContainerResultCallback> 851 export_lxd_container_callbacks_; 852 std::map<ContainerId, CrostiniResultCallback> import_lxd_container_callbacks_; 853 854 // Callbacks to run after Tremplin is started, keyed by vm_name. These are 855 // used if StartTerminaVm completes but we need to wait from Tremplin to 856 // start. 857 std::multimap<std::string, base::OnceClosure> tremplin_started_callbacks_; 858 859 // Callbacks to run after LXD is started, keyed by vm_name. Used if StartLxd 860 // completes but we need to wait for LXD to start. 861 std::map<std::string, CrostiniResultCallback> start_lxd_callbacks_; 862 863 std::map<std::string, VmInfo> running_vms_; 864 865 // Running containers as keyed by vm name. 866 std::multimap<std::string, ContainerInfo> running_containers_; 867 868 // OsRelease protos keyed by ContainerId. We populate this map even if a 869 // container fails to start normally. 870 std::map<ContainerId, vm_tools::cicerone::OsRelease> container_os_releases_; 871 std::set<ContainerId> container_upgrade_prompt_shown_; 872 873 std::vector<RemoveCrostiniCallback> remove_crostini_callbacks_; 874 875 base::ObserverList<LinuxPackageOperationProgressObserver>::Unchecked 876 linux_package_operation_progress_observers_; 877 878 base::ObserverList<PendingAppListUpdatesObserver> 879 pending_app_list_updates_observers_; 880 881 base::ObserverList<ExportContainerProgressObserver>::Unchecked 882 export_container_progress_observers_; 883 base::ObserverList<ImportContainerProgressObserver>::Unchecked 884 import_container_progress_observers_; 885 886 base::ObserverList<UpgradeContainerProgressObserver>::Unchecked 887 upgrade_container_progress_observers_; 888 889 base::ObserverList<VmShutdownObserver> vm_shutdown_observers_; 890 base::ObserverList<chromeos::VmStartingObserver> vm_starting_observers_; 891 892 // Only one restarter flow is actually running for a given container, other 893 // restarters will just have their callback called when the running restarter 894 // completes. 895 std::multimap<ContainerId, CrostiniManager::RestartId> 896 restarters_by_container_; 897 898 std::map<CrostiniManager::RestartId, std::unique_ptr<CrostiniRestarter>> 899 restarters_by_id_; 900 901 base::ObserverList<CrostiniDialogStatusObserver> 902 crostini_dialog_status_observers_; 903 base::ObserverList<CrostiniContainerPropertiesObserver> 904 crostini_container_properties_observers_; 905 906 base::ObserverList<ContainerStartedObserver> container_started_observers_; 907 base::ObserverList<ContainerShutdownObserver> container_shutdown_observers_; 908 909 base::ObserverList<CrostiniMicSharingEnabledObserver> 910 crostini_mic_sharing_enabled_observers_; 911 912 base::ObserverList<CrostiniFileChangeObserver> file_change_observers_; 913 914 // Contains the types of crostini dialogs currently open. It is generally 915 // invalid to show more than one. e.g. uninstalling and installing are 916 // mutually exclusive. 917 base::flat_set<DialogType> open_crostini_dialogs_; 918 919 // Tracks if Crostini has access to the microphone. 920 bool crostini_mic_sharing_enabled_ = false; 921 922 bool dbus_observers_removed_ = false; 923 924 base::Time time_of_last_disk_type_metric_; 925 926 std::unique_ptr<CrostiniStabilityMonitor> crostini_stability_monitor_; 927 928 std::unique_ptr<CrostiniUpgradeAvailableNotification> 929 upgrade_available_notification_; 930 931 TerminaInstaller termina_installer_{}; 932 933 // Note: This should remain the last member so it'll be destroyed and 934 // invalidate its weak pointers before any other members are destroyed. 935 base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_{this}; 936 937 DISALLOW_COPY_AND_ASSIGN(CrostiniManager); 938 }; 939 940 } // namespace crostini 941 942 #endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_MANAGER_H_ 943