#include "chrome/browser/extensions/forced_extensions/force_installed_metrics.h"
#include <optional>
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/forced_extensions/force_installed_test_base.h"
#include "chrome/browser/extensions/forced_extensions/force_installed_tracker.h"
#include "chrome/browser/extensions/forced_extensions/install_stage_tracker.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/testing_browser_process.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/install/crx_install_error.h"
#include "extensions/browser/install/sandboxed_unpacker_failure_reason.h"
#include "extensions/browser/pref_names.h"
#include "extensions/browser/updater/safe_manifest_parser.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "net/base/net_errors.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/arc_prefs.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_names.h"
#endif
namespace {
constexpr char kExtensionId3[] = …;
const int kFetchTries = …;
const int kHttpCodeForbidden = …;
constexpr char kLoadTimeStats[] = …;
constexpr char kReadyTimeStats[] = …;
constexpr char kTimedOutStats[] = …;
constexpr char kTimedOutNotInstalledStats[] = …;
constexpr char kInstallationFailureCacheStatus[] = …;
constexpr char kFailureReasonsCWS[] = …;
constexpr char kFailureReasonsSH[] = …;
constexpr char kInstallationStages[] = …;
constexpr char kInstallCreationStages[] = …;
constexpr char kInstallationDownloadingStages[] = …;
constexpr char kFailureCrxInstallErrorStats[] = …;
constexpr char kTotalCountStats[] = …;
constexpr char kNetworkErrorCodeCrxFetchRetryStats[] = …;
constexpr char kHttpErrorCodeCrxFetchRetryStatsCWS[] = …;
constexpr char kHttpErrorCodeCrxFetchRetryStatsSH[] = …;
constexpr char kFetchRetriesCrxFetchRetryStats[] = …;
constexpr char kNetworkErrorCodeCrxFetchFailedStats[] = …;
constexpr char kHttpErrorCodeCrxFetchFailedStats[] = …;
constexpr char kHttpErrorCodeCrxFetchFailedStatsCWS[] = …;
constexpr char kHttpErrorCodeCrxFetchFailedStatsSH[] = …;
constexpr char kFetchRetriesCrxFetchFailedStats[] = …;
constexpr char kNetworkErrorCodeManifestFetchRetryStats[] = …;
constexpr char kHttpErrorCodeManifestFetchRetryStatsCWS[] = …;
constexpr char kHttpErrorCodeManifestFetchRetryStatsSH[] = …;
constexpr char kFetchRetriesManifestFetchRetryStats[] = …;
constexpr char kNetworkErrorCodeManifestFetchFailedStats[] = …;
constexpr char kHttpErrorCodeManifestFetchFailedStats[] = …;
constexpr char kHttpErrorCodeManifestFetchFailedStatsCWS[] = …;
constexpr char kHttpErrorCodeManifestFetchFailedStatsSH[] = …;
constexpr char kFetchRetriesManifestFetchFailedStats[] = …;
constexpr char kSandboxUnpackFailureReason[] = …;
#if BUILDFLAG(IS_CHROMEOS_ASH)
constexpr char kFailureSessionStats[] =
"Extensions.ForceInstalledFailureSessionType";
constexpr char kStuckInCreateStageSessionType[] =
"Extensions.ForceInstalledFailureSessionType."
"ExtensionStuckInInitialCreationStage";
#endif
constexpr char kPossibleNonMisconfigurationFailures[] = …;
constexpr char kDisableReason[] = …;
constexpr char kBlocklisted[] = …;
constexpr char kWebStoreExtensionManifestInvalid[] = …;
constexpr char kOffStoreExtensionManifestInvalid[] = …;
constexpr char kManifestNoUpdatesInfo[] = …;
constexpr char kExtensionManifestInvalidAppStatusError[] = …;
constexpr char kManifestDownloadTimeStats[] = …;
constexpr char kCRXDownloadTimeStats[] = …;
constexpr char kVerificationTimeStats[] = …;
constexpr char kCopyingTimeStats[] = …;
constexpr char kUnpackingTimeStats[] = …;
constexpr char kCheckingExpectationsTimeStats[] = …;
constexpr char kFinalizingTimeStats[] = …;
constexpr char kCrxHeaderInvalidFailureIsCWS[] = …;
constexpr char kCrxHeaderInvalidFailureFromCache[] = …;
constexpr char kStuckInCreatedStageAreExtensionsEnabled[] = …;
}
namespace extensions {
ExtensionStatus;
ExtensionOrigin;
_;
Return;
class ForceInstalledMetricsTest : public ForceInstalledTestBase { … };
TEST_F(ForceInstalledMetricsTest, EmptyForcelist) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsInstalled) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionSettingsOverrideForcedList) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsInstallationTimedOut) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsManifestDownloadTime) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsCrxDownloadTime) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsCrxDownloadTimeWhenFetchedFromCache) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsReportInstallationStageTimes) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsInstalledButNotLoadedUniqueDisableReason) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsInstalledButNotLoadedMultipleDisableReason) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsInstalledButNotLoadedNoDisableReason) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsStuckInCreatedStageAreExtensionsEnabled) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionForceInstalledAndBlocklisted) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsInstallationCancelled) { … }
TEST_F(ForceInstalledMetricsTest, ForcedExtensionsAddedAfterManualExtensions) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsInstallationTimedOutDifferentReasons) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsCrxInstallErrorSandboxUnpackFailure) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsCrxHeaderInvalidFromCache) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsCrxHeaderInvalidNotFromCache) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsCrxHeaderInvalidIsMisconfiguration) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsFailureReplacedBySystemAppIsMisconfiguration) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsNoUpdatesInfoReporting) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionLoadedThenFailedWithAlreadyInstalledError) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsReady) { … }
TEST_F(ForceInstalledMetricsTest, AllExtensionsNotReady) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionsPreviousInstallationStageReportedAgain) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsDownloadingStageReportedAgain) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionsStuck) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionStuckInCreatedStage) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ForceInstalledMetricsTest, ReportManagedGuestSessionOnExtensionFailure) {
auto* fake_user_manager = new ash::FakeChromeUserManager();
user_manager::ScopedUserManager scoped_user_manager(
base::WrapUnique(fake_user_manager));
const AccountId account_id =
AccountId::FromUserEmail(profile()->GetProfileUserName());
user_manager::User* user =
fake_user_manager->AddPublicAccountUser(account_id);
fake_user_manager->UserLoggedIn(account_id, user->username_hash(),
false ,
false );
SetupForceList(ExtensionOrigin::kWebStore);
install_stage_tracker()->ReportFailure(
kExtensionId1, InstallStageTracker::FailureReason::INVALID_ID);
install_stage_tracker()->ReportCrxInstallError(
kExtensionId2,
InstallStageTracker::FailureReason::CRX_INSTALL_ERROR_OTHER,
CrxInstallErrorDetail::UNEXPECTED_ID);
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(
kFailureSessionStats,
ForceInstalledMetrics::UserType::USER_TYPE_PUBLIC_ACCOUNT, 2);
}
TEST_F(ForceInstalledMetricsTest, ReportGuestSessionOnExtensionFailure) {
auto* fake_user_manager = new ash::FakeChromeUserManager();
user_manager::ScopedUserManager scoped_user_manager(
base::WrapUnique(fake_user_manager));
user_manager::User* user = fake_user_manager->AddGuestUser();
fake_user_manager->UserLoggedIn(user->GetAccountId(), user->username_hash(),
false ,
false );
SetupForceList(ExtensionOrigin::kWebStore);
install_stage_tracker()->ReportFailure(
kExtensionId1, InstallStageTracker::FailureReason::INVALID_ID);
install_stage_tracker()->ReportCrxInstallError(
kExtensionId2,
InstallStageTracker::FailureReason::CRX_INSTALL_ERROR_OTHER,
CrxInstallErrorDetail::UNEXPECTED_ID);
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(
kFailureSessionStats, ForceInstalledMetrics::UserType::USER_TYPE_GUEST,
2);
}
TEST_F(ForceInstalledMetricsTest,
ReportGuestSessionForExtensionsStuckInCreatedStage) {
auto* fake_user_manager = new ash::FakeChromeUserManager();
user_manager::ScopedUserManager scoped_user_manager(
base::WrapUnique(fake_user_manager));
user_manager::User* user = fake_user_manager->AddGuestUser();
fake_user_manager->UserLoggedIn(user->GetAccountId(), user->username_hash(),
false ,
false );
SetupForceList(ExtensionOrigin::kWebStore);
CreateExtensionService(true);
scoped_refptr<const Extension> ext1 = CreateNewExtension(
kExtensionName1, kExtensionId1, ExtensionStatus::kLoaded);
install_stage_tracker()->ReportInstallationStage(
kExtensionId2, InstallStageTracker::Stage::CREATED);
install_stage_tracker()->ReportInstallCreationStage(
kExtensionId2, InstallStageTracker::InstallCreationStage::
NOTIFIED_FROM_MANAGEMENT_INITIAL_CREATION_FORCED);
EXPECT_TRUE(fake_timer_->IsRunning());
fake_timer_->Fire();
histogram_tester_.ExpectUniqueSample(
kFailureReasonsCWS, InstallStageTracker::FailureReason::IN_PROGRESS, 1);
histogram_tester_.ExpectBucketCount(kInstallationStages,
InstallStageTracker::Stage::CREATED, 1);
histogram_tester_.ExpectBucketCount(
kInstallCreationStages,
InstallStageTracker::InstallCreationStage::
NOTIFIED_FROM_MANAGEMENT_INITIAL_CREATION_FORCED,
1);
histogram_tester_.ExpectUniqueSample(kStuckInCreatedStageAreExtensionsEnabled,
true, 1);
histogram_tester_.ExpectBucketCount(
kFailureSessionStats, ForceInstalledMetrics::UserType::USER_TYPE_GUEST,
1);
histogram_tester_.ExpectBucketCount(
kStuckInCreateStageSessionType,
ForceInstalledMetrics::UserType::USER_TYPE_GUEST, 1);
}
#endif
TEST_F(ForceInstalledMetricsTest, ExtensionsAreDownloading) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionCrxFetchFailedCWS) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionCrxFetchFailedSelfHosted) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestFetchFailedCWS) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestFetchFailedSelfHosted) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestFetchRetryCWS) { … }
TEST_F(ForceInstalledMetricsTest,
OffStoreExtensionManifestInvalidIsMisconfiguration) { … }
TEST_F(ForceInstalledMetricsTest,
ExtensionOverridenBySettingsFailureIsMisconfiguration) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestFetchRetrySelfHosted) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionCrxFetchRetryCWS) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionCrxFetchRetrySelfHosted) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalidWebStore) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalidOffStore) { … }
TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalidAppStatusError) { … }
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentKioskModeOnlyError) { … }
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentDisallowedByPolicyTypeError) { … }
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailurePresentDisallowedByPolicyError) { … }
TEST_F(ForceInstalledMetricsTest, NonMisconfigurationFailurePresent) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentReplacedByArcAppErrorArcEnabled) {
prefs()->SetManagedPref(arc::prefs::kArcEnabled,
std::make_unique<base::Value>(true));
SetupForceList(ExtensionOrigin::kWebStore);
scoped_refptr<const Extension> ext1 = CreateNewExtension(
kExtensionName1, kExtensionId1, ExtensionStatus::kLoaded);
install_stage_tracker()->ReportFailure(
kExtensionId2, InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP);
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(kPossibleNonMisconfigurationFailures, 0,
1);
}
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentReplacedByArcAppErrorArcDisabled) {
prefs()->SetManagedPref(arc::prefs::kArcEnabled,
std::make_unique<base::Value>(false));
SetupForceList(ExtensionOrigin::kWebStore);
scoped_refptr<const Extension> ext1 = CreateNewExtension(
kExtensionName1, kExtensionId1, ExtensionStatus::kLoaded);
install_stage_tracker()->ReportFailure(
kExtensionId2, InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP);
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(kPossibleNonMisconfigurationFailures, 1,
1);
}
#endif
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentNotPerformingNewInstallError) { … }
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailureNotPresentCrxFetchUrlEmptyError) { … }
TEST_F(ForceInstalledMetricsTest,
NonMisconfigurationFailurePresentCrxFetchUrlEmptyError) { … }
TEST_F(ForceInstalledMetricsTest, NoExtensionsConfigured) { … }
TEST_F(ForceInstalledMetricsTest, CachedExtensions) { … }
}