| // Copyright 2022 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/accessibility/accessibility_dlc_installer.h" |
| |
| #include <string_view> |
| |
| #include "base/containers/contains.h" |
| #include "base/functional/bind.h" |
| #include "base/metrics/histogram_functions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/time/time.h" |
| #include "ui/accessibility/accessibility_features.h" |
| |
| namespace { |
| constexpr char kFaceGazeAssetsInstallDurationMetric[] = |
| "Accessibility.DlcInstallerFaceGazeAssetsInstallationDuration"; |
| |
| constexpr char kFaceGazeAssetsInstallationMetric[] = |
| "Accessibility.DlcInstallerFaceGazeAssetsSuccess"; |
| |
| constexpr char kPumpkinInstallationMetric[] = |
| "PumpkinInstaller.InstallationSuccess"; |
| |
| constexpr char kPumpkinInstallDurationMetric[] = |
| "Accessibility.DlcInstallerPumpkinInstallationDuration"; |
| } // namespace |
| |
| namespace ash { |
| |
| AccessibilityDlcInstaller::Callbacks::Callbacks(InstalledCallback on_installed, |
| ProgressCallback on_progress, |
| ErrorCallback on_error) { |
| on_installed_ = std::move(on_installed); |
| on_progress_ = std::move(on_progress); |
| on_error_ = std::move(on_error); |
| } |
| |
| AccessibilityDlcInstaller::Callbacks::~Callbacks() = default; |
| |
| void AccessibilityDlcInstaller::Callbacks::RunOnInstalled( |
| const bool success, |
| std::string root_path) { |
| DCHECK(!on_installed_.is_null()); |
| std::move(on_installed_).Run(success, root_path); |
| } |
| |
| void AccessibilityDlcInstaller::Callbacks::RunOnProgress(double progress) { |
| DCHECK(!on_progress_.is_null()); |
| on_progress_.Run(progress); |
| } |
| |
| void AccessibilityDlcInstaller::Callbacks::RunOnError(std::string_view error) { |
| DCHECK(!on_error_.is_null()); |
| std::move(on_error_).Run(error); |
| } |
| |
| AccessibilityDlcInstaller::AccessibilityDlcInstaller() = default; |
| AccessibilityDlcInstaller::~AccessibilityDlcInstaller() = default; |
| |
| void AccessibilityDlcInstaller::MaybeInstall(DlcType type, |
| InstalledCallback on_installed, |
| ProgressCallback on_progress, |
| ErrorCallback on_error) { |
| if (pending_requests_[type]) { |
| std::move(on_error).Run(GetPendingDlcRequestErrorMessage(type)); |
| return; |
| } |
| |
| callbacks_.insert_or_assign( |
| type, |
| std::make_unique<Callbacks>(std::move(on_installed), |
| std::move(on_progress), std::move(on_error))); |
| pending_requests_.insert_or_assign(type, true); |
| DlcserviceClient::Get()->GetDlcState( |
| GetDlcName(type), |
| base::BindOnce(&AccessibilityDlcInstaller::MaybeInstallHelper, |
| GetWeakPtr(), type)); |
| } |
| |
| void AccessibilityDlcInstaller::MaybeInstallHelper( |
| DlcType type, |
| std::string_view error, |
| const dlcservice::DlcState& dlc_state) { |
| pending_requests_.insert_or_assign(type, false); |
| if (error != dlcservice::kErrorNone) { |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnError(error); |
| } |
| return; |
| } |
| |
| switch (dlc_state.state()) { |
| case dlcservice::DlcState_State_INSTALLING: |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnError(GetDlcInstallingErrorMessage(type)); |
| } |
| return; |
| case dlcservice::DlcState_State_INSTALLED: |
| installed_dlcs_.insert(type); |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnInstalled(true, dlc_state.root_path()); |
| } |
| return; |
| default: |
| break; |
| } |
| |
| // Install DLC. |
| pending_requests_.insert_or_assign(type, true); |
| dlcservice::InstallRequest install_request; |
| install_request.set_id(GetDlcName(type)); |
| DlcserviceClient::Get()->Install( |
| install_request, |
| base::BindOnce(&AccessibilityDlcInstaller::OnInstalled, GetWeakPtr(), |
| type, base::Time::Now()), |
| base::BindRepeating(&AccessibilityDlcInstaller::OnProgress, GetWeakPtr(), |
| type)); |
| } |
| |
| void AccessibilityDlcInstaller::OnInstalled( |
| DlcType type, |
| const base::Time start_time, |
| const DlcserviceClient::InstallResult& install_result) { |
| pending_requests_.insert_or_assign(type, false); |
| |
| // Record success metric. |
| switch (type) { |
| case DlcType::kFaceGazeAssets: |
| base::UmaHistogramBoolean(kFaceGazeAssetsInstallationMetric, |
| install_result.error == dlcservice::kErrorNone); |
| break; |
| case DlcType::kPumpkin: |
| base::UmaHistogramBoolean(kPumpkinInstallationMetric, |
| install_result.error == dlcservice::kErrorNone); |
| break; |
| } |
| |
| if (install_result.error != dlcservice::kErrorNone) { |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnError(install_result.error); |
| } |
| return; |
| } |
| |
| // Record install duration metric. |
| const base::TimeDelta install_duration = base::Time::Now() - start_time; |
| switch (type) { |
| case DlcType::kFaceGazeAssets: |
| base::UmaHistogramTimes(kFaceGazeAssetsInstallDurationMetric, |
| install_duration); |
| break; |
| case DlcType::kPumpkin: |
| base::UmaHistogramTimes(kPumpkinInstallDurationMetric, install_duration); |
| break; |
| } |
| |
| installed_dlcs_.insert(type); |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnInstalled(true, install_result.root_path); |
| } |
| } |
| |
| void AccessibilityDlcInstaller::OnProgress(DlcType type, double progress) { |
| if (GetCallbacks(type)) { |
| GetCallbacks(type)->RunOnProgress(progress); |
| } |
| } |
| |
| AccessibilityDlcInstaller::Callbacks* AccessibilityDlcInstaller::GetCallbacks( |
| DlcType type) { |
| if (!callbacks_[type]) { |
| return nullptr; |
| } |
| |
| return callbacks_[type].get(); |
| } |
| |
| std::string AccessibilityDlcInstaller::GetDlcName(DlcType type) { |
| switch (type) { |
| case DlcType::kFaceGazeAssets: |
| return "facegaze-assets"; |
| case DlcType::kPumpkin: |
| return "pumpkin"; |
| } |
| } |
| |
| std::string AccessibilityDlcInstaller::GetDlcInstallingErrorMessage( |
| DlcType type) { |
| return base::StringPrintf("%s already installing.", GetDlcName(type).c_str()); |
| } |
| |
| std::string AccessibilityDlcInstaller::GetPendingDlcRequestErrorMessage( |
| DlcType type) { |
| return base::StringPrintf("Cannot install %s, DLC request in progress.", |
| GetDlcName(type).c_str()); |
| } |
| |
| bool AccessibilityDlcInstaller::IsFaceGazeAssetsInstalled() const { |
| return base::Contains(installed_dlcs_, DlcType::kFaceGazeAssets); |
| } |
| |
| bool AccessibilityDlcInstaller::IsPumpkinInstalled() const { |
| return base::Contains(installed_dlcs_, DlcType::kPumpkin); |
| } |
| |
| base::WeakPtr<AccessibilityDlcInstaller> |
| AccessibilityDlcInstaller::GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| } // namespace ash |