chromium/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.cc

// 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/apps/app_service/metrics/app_platform_metrics_service_test_base.h"

#include <memory>

#include "base/memory/ptr_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h"
#include "chrome/browser/apps/app_service/publishers/app_publisher.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/trusted_vault/trusted_vault_service_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/services/app_service/public/cpp/app_types.h"
#include "components/services/app_service/public/cpp/instance.h"
#include "components/services/app_service/public/cpp/instance_registry.h"
#include "components/sync/test/test_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/ukm/test_ukm_recorder.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/browser/browser_context.h"
#include "ui/aura/window.h"

namespace apps {
namespace {

constexpr char kStartTime[] = "1 Jan 2021 21:00";
constexpr char kTestUserEmail[] = "[email protected]";

std::unique_ptr<KeyedService> TestingSyncFactoryFunction(
    content::BrowserContext* context) {
  return std::make_unique<syncer::TestSyncService>();
}

}  // namespace

TestApp::TestApp(std::string app_id,
                 AppType app_type,
                 std::string publisher_id,
                 Readiness readiness,
                 InstallReason install_reason,
                 InstallSource install_source,
                 bool should_notify_initialized,
                 bool is_platform_app,
                 WindowMode window_mode)
    : app_id(std::move(app_id)),
      app_type(app_type),
      publisher_id(std::move(publisher_id)),
      readiness(readiness),
      install_reason(install_reason),
      install_source(install_source),
      should_notify_initialized(should_notify_initialized),
      is_platform_app(is_platform_app),
      window_mode(window_mode) {}

TestApp::TestApp() = default;

TestApp::TestApp(const TestApp& other) = default;

TestApp::TestApp(TestApp&& other) = default;

AppPtr MakeApp(TestApp app) {
  auto result = AppPublisher::MakeApp(app.app_type, app.app_id, app.readiness,
                                      app.publisher_id, app.install_reason,
                                      app.install_source);
  result->publisher_id = app.publisher_id;
  result->is_platform_app = app.is_platform_app;
  result->window_mode = app.window_mode;
  return result;
}

void AddApp(AppServiceProxy* proxy, TestApp app) {
  CHECK(proxy);
  std::vector<AppPtr> deltas;
  deltas.push_back(MakeApp(app));
  proxy->OnApps(std::move(deltas), app.app_type, app.should_notify_initialized);
}

AppPlatformMetricsServiceTestBase::AppPlatformMetricsServiceTestBase() =
    default;

AppPlatformMetricsServiceTestBase::~AppPlatformMetricsServiceTestBase() =
    default;

void AppPlatformMetricsServiceTestBase::SetUp() {
  AddRegularUser(kTestUserEmail);
  test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();

  base::Time start_time;
  EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &start_time));
  base::TimeDelta forward_by = start_time - base::Time::Now();
  EXPECT_LT(base::TimeDelta(), forward_by);
  task_environment_.AdvanceClock(forward_by);
  GetPrefService()->SetInteger(
      kAppPlatformMetricsDayId,
      start_time.UTCMidnight().since_origin().InDaysFloored());

  if (!::chromeos::PowerManagerClient::Get()) {
    ::chromeos::PowerManagerClient::InitializeFake();
  }

  // Wait for AppServiceProxy to be ready.
  app_service_test_.SetUp(profile());

  app_platform_metrics_service_ =
      std::make_unique<AppPlatformMetricsService>(profile());

  // Install a BuiltIn app before app_platform_metrics_service_ started to
  // verify the install AppKM.
  AddApp(AppServiceProxyFactory::GetForProfile(profile()),
         {/*app_id=*/"bu", AppType::kBuiltIn, "", Readiness::kReady,
          InstallReason::kSystem, InstallSource::kSystem,
          /*should_notify_initialized=*/true});

  app_platform_metrics_service_->Start(
      AppServiceProxyFactory::GetForProfile(profile())->AppRegistryCache(),
      AppServiceProxyFactory::GetForProfile(profile())->InstanceRegistry(),
      AppServiceProxyFactory::GetForProfile(profile())
          ->AppCapabilityAccessCache());
}

void AppPlatformMetricsServiceTestBase::TearDown() {
  app_platform_metrics_service_.reset();
  ::chromeos::PowerManagerClient::Shutdown();
}

void AppPlatformMetricsServiceTestBase::InstallOneApp(
    const std::string& app_id,
    AppType app_type,
    const std::string& publisher_id,
    Readiness readiness,
    InstallSource install_source,
    bool is_platform_app,
    WindowMode window_mode,
    InstallReason install_reason) {
  InstallOneApp({app_id, app_type, publisher_id, readiness, install_reason,
                 install_source,
                 /*should_notify_initialized=*/false, is_platform_app,
                 window_mode});
}

void AppPlatformMetricsServiceTestBase::InstallOneApp(TestApp app) {
  auto* proxy = AppServiceProxyFactory::GetForProfile(profile());
  AddApp(proxy, app);
}

void AppPlatformMetricsServiceTestBase::ResetAppPlatformMetricsService() {
  app_platform_metrics_service_.reset();
  app_platform_metrics_service_ =
      std::make_unique<AppPlatformMetricsService>(profile());

  app_platform_metrics_service_->Start(
      AppServiceProxyFactory::GetForProfile(profile())->AppRegistryCache(),
      AppServiceProxyFactory::GetForProfile(profile())->InstanceRegistry(),
      AppServiceProxyFactory::GetForProfile(profile())
          ->AppCapabilityAccessCache());
}

void AppPlatformMetricsServiceTestBase::ModifyInstance(
    const std::string& app_id,
    aura::Window* window,
    InstanceState state) {
  InstanceParams params(app_id, window);
  params.state = std::make_pair(state, base::Time::Now());
  AppServiceProxyFactory::GetForProfile(profile())
      ->InstanceRegistry()
      .CreateOrUpdateInstance(std::move(params));
}

void AppPlatformMetricsServiceTestBase::ModifyInstance(
    const base::UnguessableToken& instance_id,
    const std::string& app_id,
    aura::Window* window,
    InstanceState state) {
  auto instance = std::make_unique<Instance>(app_id, instance_id, window);
  instance->UpdateState(state, base::Time::Now());
  AppServiceProxyFactory::GetForProfile(profile())
      ->InstanceRegistry()
      .OnInstance(std::move(instance));
}

void AppPlatformMetricsServiceTestBase::ModifyWebAppInstance(
    const std::string& app_id,
    aura::Window* window,
    InstanceState state) {
  InstanceParams params(app_id, window);
  params.state = std::make_pair(state, base::Time::Now());
  AppServiceProxyFactory::GetForProfile(profile())
      ->InstanceRegistry()
      .CreateOrUpdateInstance(std::move(params));
}

sync_preferences::TestingPrefServiceSyncable*
AppPlatformMetricsServiceTestBase::GetPrefService() {
  return testing_profile_->GetTestingPrefService();
}

std::unique_ptr<AppPlatformMetricsService>
AppPlatformMetricsServiceTestBase::GetAppPlatformMetricsService() {
  return std::move(app_platform_metrics_service_);
}

int AppPlatformMetricsServiceTestBase::GetDayIdPref() {
  return GetPrefService()->GetInteger(kAppPlatformMetricsDayId);
}

void AppPlatformMetricsServiceTestBase::AddRegularUser(
    const std::string& email) {
  fake_user_manager_ = new ash::FakeChromeUserManager();
  scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
      base::WrapUnique(fake_user_manager_.get()));
  AccountId account_id = AccountId::FromUserEmail(email);
  const user_manager::User* user = fake_user_manager_->AddUser(account_id);
  fake_user_manager_->UserLoggedIn(account_id, user->username_hash(),
                                   /*browser_restart=*/false,
                                   /*is_child=*/false);
  fake_user_manager_->SimulateUserProfileLoad(account_id);

  TestingProfile::Builder builder;
  builder.AddTestingFactory(TrustedVaultServiceFactory::GetInstance(),
                            TrustedVaultServiceFactory::GetDefaultFactory());
  builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
                            SyncServiceFactory::GetDefaultFactory());
  testing_profile_ = builder.Build();

  ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, profile());

  sync_service_ = static_cast<syncer::TestSyncService*>(
      SyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
          profile(), base::BindRepeating(&TestingSyncFactoryFunction)));
  sync_service_->SetInitialSyncFeatureSetupComplete(true);
}

}  // namespace apps