| // Copyright 2023 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/borealis/borealis_survey_handler.h" |
| |
| #include "base/containers/flat_map.h" |
| #include "base/feature_list.h" |
| #include "base/functional/bind.h" |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/system/sys_info.h" |
| #include "base/task/task_traits.h" |
| #include "base/task/thread_pool.h" |
| #include "chrome/browser/ash/borealis/borealis_service.h" |
| #include "chrome/browser/ash/borealis/borealis_util.h" |
| #include "chrome/browser/ash/borealis/borealis_window_manager.h" |
| #include "chrome/browser/ash/guest_os/guest_os_registry_service.h" |
| #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h" |
| #include "chrome/browser/ash/hats/hats_config.h" |
| #include "chrome/browser/ash/profiles/profile_helper.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/display/screen.h" |
| |
| namespace borealis { |
| |
| BorealisSurveyHandler::BorealisSurveyHandler( |
| Profile* profile, |
| BorealisWindowManager* window_manager) |
| : profile_(profile) { |
| if (!base::FeatureList::IsEnabled(ash::kHatsBorealisGamesSurvey.feature)) { |
| VLOG(1) << "Borealis survey feature is not enabled"; |
| return; |
| } |
| lifetime_observation_.Observe(window_manager); |
| } |
| BorealisSurveyHandler::~BorealisSurveyHandler() = default; |
| |
| std::optional<int> BorealisSurveyHandler::GetGameId(const std::string& app_id) { |
| // Attempt to get the Borealis app ID. |
| // TODO(b/173977876): Implement this in a more reliable way. |
| std::optional<int> game_id; |
| std::optional<guest_os::GuestOsRegistryService::Registration> registration = |
| guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_) |
| ->GetRegistration(app_id); |
| if (registration.has_value()) { |
| game_id = borealis::ParseSteamGameId(registration->Exec()); |
| } |
| return game_id; |
| } |
| |
| base::flat_map<std::string, std::string> BorealisSurveyHandler::GetSurveyData( |
| std::string owner_id, |
| std::string app_id, |
| std::string window_title, |
| std::optional<int> game_id) { |
| // Number of monitors |
| int internal_displays = 0; |
| int external_displays = 0; |
| for (const display::Display& d : |
| display::Screen::GetScreen()->GetAllDisplays()) { |
| if (d.IsInternal()) { |
| internal_displays++; |
| } else { |
| external_displays++; |
| } |
| } |
| |
| // Proton/SLR versions |
| borealis::CompatToolInfo compat_tool_info; |
| std::string output; |
| if (borealis::GetCompatToolInfo(owner_id, &output)) { |
| compat_tool_info = borealis::ParseCompatToolInfo(game_id, output); |
| } else { |
| LOG(WARNING) << "Failed to get compat tool version info:"; |
| LOG(WARNING) << output; |
| } |
| |
| // Steam GameID |
| if (!game_id.has_value() && compat_tool_info.game_id.has_value()) { |
| game_id = compat_tool_info.game_id.value(); |
| } |
| std::string game_id_value = ""; |
| if (game_id.has_value()) { |
| game_id_value = base::StringPrintf("%d", game_id.value()); |
| } |
| |
| base::flat_map<std::string, std::string> survey_data = { |
| {"appName", window_title}, |
| {"board", base::SysInfo::HardwareModelName()}, |
| {"specs", |
| base::StringPrintf( |
| "%ldGB; %s", |
| (long)(base::SysInfo::AmountOfPhysicalMemory().InBytesUnsigned() / |
| (1000 * 1000 * 1000)), |
| base::SysInfo::CPUModelName().c_str())}, |
| {"monitorsInternal", base::NumberToString(internal_displays)}, |
| {"monitorsExternal", base::NumberToString(external_displays)}, |
| {"proton", compat_tool_info.proton}, |
| {"steam", compat_tool_info.slr}, |
| {"gameId", game_id_value}}; |
| return survey_data; |
| } |
| |
| void BorealisSurveyHandler::OnAppFinished(const std::string& app_id, |
| aura::Window* last_window) { |
| if (IsNonGameBorealisApp(app_id)) { |
| return; |
| } |
| if (ash::HatsNotificationController::ShouldShowSurveyToProfile( |
| profile_, ash::kHatsBorealisGamesSurvey)) { |
| base::ThreadPool::PostTaskAndReplyWithResult( |
| FROM_HERE, base::MayBlock(), |
| base::BindOnce(&GetSurveyData, |
| ash::ProfileHelper::GetUserIdHashFromProfile(profile_), |
| std::string(app_id), |
| base::UTF16ToUTF8(last_window->GetTitle()), |
| GetGameId(app_id)), |
| base::BindOnce(&BorealisSurveyHandler::CreateNotification, |
| weak_factory_.GetWeakPtr())); |
| } |
| } |
| |
| void BorealisSurveyHandler::CreateNotification( |
| base::flat_map<std::string, std::string> survey_data) { |
| hats_notification_controller_ = new ash::HatsNotificationController( |
| profile_, ash::kHatsBorealisGamesSurvey, survey_data, |
| l10n_util::GetStringUTF16(IDS_BOREALIS_HATS_TITLE), |
| l10n_util::GetStringUTF16(IDS_BOREALIS_HATS_BODY)); |
| } |
| |
| void BorealisSurveyHandler::OnWindowManagerDeleted( |
| BorealisWindowManager* window_manager) { |
| lifetime_observation_.Reset(); |
| } |
| |
| } // namespace borealis |